C# 动态创建类,动态创建表,支持多库的数据库维护方案

2023-10-22 11:16:04 浏览数 (1)

一、创建表

SqlSugar支持了3种模式的建表(无实体建表、实体建表,实体特性建表),非常的灵活

可以多个数据库 MYSQL MSSQL ORACLE SQLITE PGSQL 等用同一语法创建数据库,最近TDengine,达梦和高斯等国产数据库也都实现了支持。可谓可圈可点。不需要考虑数据库的兼容性。

1.1、通过特性建表

我们可以通过创建实体来进行建表

代码语言:javascript复制
public class CodeFirstTable1
{
        [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
        public int Id { get; set; }
        public string Name { get; set; }
        //ColumnDataType 自定格式的情况 length不要设置 (想要多库兼容看4.2和9)
        [SugarColumn(ColumnDataType = "Nvarchar(255)")]
        public string Text { get; set; }
        [SugarColumn(IsNullable = true)]//可以为NULL
        public DateTime CreateTime { get; set; }
}
  
/***创建单个表***/
db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(CodeFirstTable1));//这样一个表就能成功创建了
/***手动建多个表***/
db.CodeFirst.SetStringDefaultLength(200)
.InitTables(typeof(CodeFirstTable1),typeof(CodeFirstTable2));

建表特性如下

2.2、无特性建表

如果我们的实体不需要加特性,那么我们可以通过无特性方式建表

代码语言:javascript复制
SugarClient db = new SqlSugarClient(new ConnectionConfig()
{
    DbType = DbType.SqlServer,
    ConnectionString = Config.ConnectionString3,
    InitKeyType = InitKeyType.Attribute,
    IsAutoCloseConnection = true,
    ConfigureExternalServices = new ConfigureExternalServices()
    {
        EntityService = (s, p) =>
        {
            //如果是Order实体进行相关配置
            p.IfTable<Order>()
            .UpdateProperty(it => it.id, it =>
            {
                it.IsIdentity = true;
                it.IsPrimarykey = true;
            })
            .UpdateProperty(it => it.Name, it => {
                it.Length = 100;
                it.IsNullable = true;
   
            })
            .OneToOne(it => it.Item, nameof(Order.ItemId));
               
            //如果Custom实体进行相关配置
             p.IfTable<Custom>()
             .UpdateProperty(it => it.id, it =>
             {
                it.IsIdentity = true;
                it.IsPrimarykey = true;
             })
              .UpdateProperty(it => it.Text, it => {
                it.DataType= StaticConfig.CodeFirst_BigString;//支持多库的MaxString用法
              })
               
                           
            //可以结合全局逻辑一起使用,下面的和上面的有冲突的话,下面会覆盖上面的
                
               
            //统一设置 nullable等于isnullable=true
            //低版本C#看标题2.2
             if(p.IsPrimaryKey==false&&new NullabilityInfoContext()
                         .Create(c).WriteState is NullabilityState.Nullable)
             {
                           p.IsNullable = true;
             }
               
                
                
        }
    }
});
//性能说明:
//EntityService 相同实体只会执行一次性不需太操作
1.3、无实体建表

功能与实体建类一模一样,如果使用SqlSugar中间标准,可以支持多个数据库一套代码建表

代码语言:javascript复制
var type = db.DynamicBuilder().CreateClass("UnitEntityA",
               new SugarTable()
               {
                   TableDescription = "表备注",
                   //DisabledUpdateAll=true 可以禁止更新只创建
               }
           )
          .CreateProperty("Id", typeof(int), new SugarColumn() { IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "列备注" })
          .CreateProperty("Name", typeof(string), new SugarColumn() {Length=200, ColumnDescription = "列备注" })
          .BuilderType();
 
           db.CodeFirst.InitTables(type);

二、数据库维护

SqlSugar有一套数据库维护API,并且能够很好的支持多种数据库,例如备份数据库等常用功能

代码语言:javascript复制
//例1 获取所有表
var tables = db.DbMaintenance.GetTableInfoList(false);//true 走缓存 false不走缓存
foreach (var table in tables)
{
     Console.WriteLine(table.Description);//输出表信息
       
     //获取列信息
     //var columns=db.DbMaintenance.GetColumnInfosByTableName("表名",false);
}
  
//例2
db.DbMaintenance.IsAnyTable("tablename",false)//验证表名是否缓存不走缓存

所有API,更细节的内容可以参考SqlSugar官网。

三、跨库支持

可以自动识别在哪个库

实体

代码语言:javascript复制
[TenantAttribute("1")]//对应ConfigId
public class C1Table
{
   public string Id { get; set; }
}
   
[TenantAttribute("2")]
public class C2Table
{
    public string Id { get; set; }
}
查询
代码语言:javascript复制
//通过ConfigId进行数据库区分
var db = new SqlSugarClient(new List<ConnectionConfig>()
{
 //这儿声名所有上下文都生效
 new ConnectionConfig(){ConfigId="0",DbType=DbType.SqlServer,ConnectionString=..,IsAutoCloseConnection=true},
 new ConnectionConfig(){ConfigId="1",DbType=DbType.MySql,ConnectionString=..,IsAutoCloseConnection=true  }
});
//自动跨库联表查询
var query5 = db.QueryableWithAttr<Order>()//如果MySql和SqlServer自动支持同服务器的跨库联表查询
         .LeftJoin<Custom>   ((o, cus ) => o.CustomId == cus.Id)//多个条件用&&
         .LeftJoin<OrderDetail> ((o, cus, oritem) => o.Id == oritem.OrderId)
         .Where(o => o.Id == 1) 
         .Select((o, cus , oritem) => new ViewOrder { Id = o.Id, CustomName = cus.Name })
         .ToList(); 
//手动跨库联表查询 ,这种方式结合dblink可以跨服务器
var query5 = db.Queryable().As("xxx.表名")
         .LeftJoin<Custom>   ((o, cus ) => o.CustomId == cus.Id ,"yyyy.表名")
         .LeftJoin<OrderDetail> ((o, cus, oritem) => o.Id == oritem.OrderId ,"zzzz.名表")
         .Where(o => o.Id == 1) 
         .Select((o, cus , oritem) => new ViewOrder { Id = o.Id, CustomName = cus.Name })
         .ToList();

四、过滤器

SqlSugar支持了全新的过滤器,可以是接口,集成该接口的类都生效,支持多表查询

代码语言:javascript复制
db.QueryFilter
.AddTableFilter<IDeletedFilter>(it => it.IsDeleted==false)//IDeletedFilter是自定义接口,继承这个接口的实体有效
.AddTableFilterIF<ITenantFilter>(isAdmint==false,it=>it.OrgId==用户OrgId);//ITenantFilter自定义接口
  
//用例1:单条语句清空,只影响当前语句
db.Queryable<Order>().ClearFilter().ToList();//所有过滤器都无效
db.Queryable<Order>().ClearFilter<IDeletedFilter>().ToList();//只有IDeletedFilter过滤器无效
db.Queryable<Order>().ClearFilter<IDeletedFilter,ITenantFilter>().ToList();//IDeletedFilter ITenantFilter无效
    
//用例2:当前上下文清空 ,不会影响其他请求,只是当前请求清空
db.QueryFilter.Clear();
db.QueryFilter.Clear<IDeletedFilter>();
  
//用例3:清空并还原 ,不会影响其他请求,只是当前请求清空
db.QueryFilter.ClearAndBackup();//有多个重载 ClearAndBackup<T,T2>();
db.Queryable<Order>().ToList();
db.QueryFilter.Restore();//还原过滤器 (适合下面代码还需要过滤器情况)

五、子查询升级

1、ToList() 可以直接查询一个对象

2、First() 可以直接查单个对象

3、ToList(it=>it.Id) 可以查List< int >一个字段集合

4、SelectStringJoin(z => z.Name, ",") 子查询将一列用逗号拼接成字符串

代码语言:javascript复制
var list=db.Queryable< Order >()
.Select(it => new
        {
          CustomId = it.CustomId,
          OrderId = it.Id,
          OrderName = it.Name,
          CustomList = SqlFunc.Subqueryable< Custom >().Where(c => c.Id == it.CustomId).ToList()
        })
       .ToList();

六、自定义类型支持

自定义类型转换器

下面只是讲解怎么定义转换器,ORM自带的功能就包含下面功能,只是用来讲解

代码语言:javascript复制
public class DictionaryConvert : ISugarDataConverter
{
public SugarParameter ParameterConverter<T>(object value, int i)
{
//该功能ORM自带的IsJson就能实现这里只是用这个用例来给大家学习
var name = "@myp"   i;
var str = new SerializeService().SerializeObject(value);
return new SugarParameter(name, str);
}
 
public T QueryConverter<T>(IDataRecord dr, int i)
{
//打断点调试
//该功能ORM自带的IsJson就能实现这里只是用这个用例来给大家学习
var str = dr.GetValue(i)   "";
return new SerializeService().DeserializeObject<T>(str);
}
}
//使用自定义转换器
[SugarColumn(ColumnDataType="varchar(2000)",SqlParameterDbType=typeof(DictionaryConvert))]
public Dictionary<string, object> DcValue { get; set; }//5.1.3.53-preview08 

总结

SqlSugar在2021年到2022年大量的开源应用使用了SqlSugar,带动了SqlSugar的快速发展。

【日拱一卒,必有所获!】

0 人点赞