C# 动态创建类,动态创建表,支持多库的数据库维护方案
简介
本文主要介绍使用 利用 SqlSugar 来实现多数据库的维护 ,动态建类CRUD,动态建表 ,全局过滤器 ,跨库查询等功能
1、创建表
SqlSugar支持了3种模式的建表(无实体建表、实体建表,实体特性建表),非常的灵活
可以多个数据库 MYSQL MSSQL ORACLE SQLITE PGSQL 等用同一语法创建数据库,不需要考虑数据库的兼容性
中间标准:
string 大文本 |
5.1.3.44-preview06 推荐 [SugarColumn(ColumnDataType = StaticConfig.CodeFirst_BigString)] |
string 设置长度的字符串 |
[SugarColumn(Length=10)] public string FieldName{ get; set; } |
int 整数 |
public int FieldName{ get; set; } |
short 整数小 |
public short FieldName{ get; set; } |
long 大数字 |
public long FieldName{ get; set; } |
bool 真假 |
public bool FieldName{ get; set; } |
decimal 默认 |
public decimal FieldName{ get; set; } |
decimal 自定义 |
//18,2 18,4 18,6 这几种兼容性好 [SugarColumn(Length=18,DecimalDigits=2)] public decimal FieldName{ get; set; }
|
DateTime 时间 |
public DateTime FieldName{ get; set; } |
枚举 (数据库存int) |
public 枚举 FieldName{ get; set; } |
byte[] 二进制 |
public byte[] FileInfo{get;set;} 建议:升级到 SqlSugarCore 5.1.3.46-preview09 及以上 对多库支持了比较好 |
SqlServer特殊配置:和他库不同一般选用Nvarchar,可以使用这个配置让他和其他数据库区分(其他库是varchar) |
DbType = SqlSugar.DbType.SqlServer, ConnectionString ="字符串", IsAutoCloseConnection = true ,
} |
1.1通过特性建表
我们可以通过创建实体来进行建表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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)); |
建表特性如下
名称 | 描述 |
---|---|
IsIdentity | 是否创建自增标识 |
IsPrimaryKey | 是否创建主键标识 |
ColumnName | 创建数据库字段的名称(默认取实体类属性名称) |
ColumnDataType |
创建数据库字段的类型 用法1: “varchar(20)” 不需要设置长度 用法2: 不设置该参数 系统会根据C#类型自动生成相应的数据库类型 用法3: 多库兼容可以用 :看标题9 |
IsIgnore | ORM不处理该列 |
ColumnDescription | 备注 表注释 (新版本支持XML文件) |
Length | 长度 设成10会生成 xxx类型(10), 没括号的不设置 |
IsNullable | 是否可以为null默为false |
DecimalDigits | 精度 如 decimal(18,2) length=18,DecimalDigits=2 |
OracleSequenceName | 设置Oracle序列,设置后该列等同于自增列 |
OldColumnName | 修改列名用,这样不会新增或者删除列 |
IndexGroupNameList | 已弃用 ,新用法看文档4.3 |
UniqueGroupNameList | 已弃用, 新用法看文档4.3 |
注意:有2个属性用处不同 DefaultValue IsOnlyIgnoreInsert |
DefaultValue=默认值 用来建表设置字段默认值 IsOnlyIgnoreInsert=true 插入数据时取默认值 很多情况需要2个一起使用 如果只建表不插入数据用1个 如果建表并且插入数据用2个 |
2.2无特性建表
如果我们的实体不需要加特性,那么我们可以通过特性方式建表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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中间标准可以支持多个数据库一套代码建表
1 2 3 4 5 6 7 8 9 10 11 12 | 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); |
3、数据库维护
SqlSugar有一套数据库维护API,并且能够很好的支持多种数据库,例如备份数据库等常用功能
1 2 3 4 5 6 7 8 9 10 11 12 | //例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
GetDataBaseList | 获取所有数据库名称 | List |
GetViewInfoList | 查询所有视图 | List |
GetTableInfoList | 获取所有表,查询所有的表 (GetTableInfoList(是否缓存)) | List |
GetColumnInfosByTableName |
获取列根据表名,获取字段,字段信 息GetColumnInfosByTableName(表名,是否缓存) |
List |
GetIsIdentities | 获取自增列 | List |
GetPrimaries | 获取主键 | List |
IsAnyTable | 表是否存在,判断表存不存在 ( IsAny(表名,是否缓存)) | bool |
IsAnyColumn | 列是否存在 | bool |
IsPrimaryKey | 主键是否存在 | bool |
IsIdentity | 自增是否存在 | bool |
IsAnyConstraint | 约束是否存在 | bool |
DropTable | 删除表 | bool |
TruncateTable | 清空表 | bool |
CreateTable |
看标题 1.1,1.2,1.3 |
bool |
AddColumn | 添加列 | bool |
UpdateColumn | 更新列 | bool |
AddPrimaryKey | 添加主键 | bool |
DropConstraint | 删除约束 | bool |
BackupDataBase | 备份库 | bool |
DropColumn | 删除列 | bool |
RenameColumn | 重命名列 | bool |
AddDefaultValue | 添加默认值 | bool |
AddTableRemark | 添加表描述,表注释 | bool |
AddColumnRemark | 添加列描述,表注释 | bool |
DeleteColumnRemark | 删除列描述,表注释 | bool |
RenameTable | 重命名表 | bool |
CreateIndex | 创建索引,唯一约束(唯一索引) | bool |
IsAnyIndex | 索引是否存在 | bool |
GetIndexList | 获取所有索引 | |
GetProcList | 获取所有存储过程 |
2、跨库支持
可以自动识别在哪个库
实体
1 2 3 4 5 6 7 8 9 10 11 | [TenantAttribute( "1" )] //对应ConfigId public class C1Table { public string Id { get ; set ; } } [TenantAttribute( "2" )] public class C2Table { public string Id { get ; set ; } } |
查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //通过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(); |
插入
1 | db.InsertableWithAttr(list).Execommand() |
更新
1 | db.UpdateableWithAttr(list).Execommand() |
删除
1 | db.UpdateableWithAttr(list).Execommand() |
只要实体配置了数据库,就不要考虑换库了,直接使用,并且支持事务
3、过滤器
SqlSugar支持了全新的过滤器,可以是接口,集成该接口的类都生效,支持多表查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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(); //还原过滤器 (适合下面代码还需要过滤器情况) |
4、子查询升级
1. ToList() 可以直接查询一个对象
2. First() 可以直接查单个对象
3.ToList(it=>it.Id) 可以查List<int>一个字段集合
4..SelectStringJoin(z => z.Name, ",") 子查询将一列用逗号拼接成字符串
1 2 3 4 5 6 7 8 9 | 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(); |
5、自定义类型支持
5.1 自定义类型转换器
下面只是讲解怎么定义转换器,ORM自带的功能就包含下面功能,只是用来讲解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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 |
现有类型支持
5.1 json类型
https://www.donet5.com/Home/Doc?typeId=1232
5.2 枚举类型
int存储:直接用就行了
1 | public DbType DcValue { get ; set ; } |
string存储:高版本如下写法
1 2 | [SugarColumn(ColumnDataType= "varchar(20)" ,SqlParameterDbType= typeof (EnumToStringConvert))] public DbType DcValue { get ; set ; } |
3.数据库独有类型支持
看左边菜单 【数据库特性】 该菜单下面有 SqlServer菜单或者MySql菜单等 , 针对不同数据库都有专门的介绍
6、动态建类,CRUD
如果用DataTable和字典去操作数据库,那么在多库兼容上是不够用的,很多实体功能不能用,比如过滤器和AOP等等
SqlSugar支持了 动态建类,来实现CRUD
//动态建类可以继承接口有重载 var type = db.DynamicBuilder().CreateClass("table1", new SugarTable() { }) .CreateProperty("Id", typeof(int),new SugarColumn() { IsPrimaryKey = true, IsIdentity = true }) .CreateProperty("Name",typeof(string), new SugarColumn() { }) .WithCache()//缓存起来根据表名和字段名组合的KEY .BuilderType(); db.CodeFirst.InitTables(type); var value= db.DynamicBuilder().CreateObjectByType(type,new Dictionary<string, object>() { { "Id", 1 }, { "Name", "jack" } }); db.InsertableByObject(value).ExecuteCommand(); db.UpdateableByObject(value).ExecuteCommand(); db.DeleteableByObject(value).ExecuteCommand(); db.StorageableByObject(value).ExecuteCommand();//插入或者更新 db.Queryable<object>().AsType(type).Filter(type).ToList();
总结
SqlSugar在2021年到2022年大量的开源应用使用了SqlSugar,带动了SqlSugar的快速发展,我这边要感谢大家
Admin.NET通用管理平台
ZrAdminNetCore 后台
管理Yi框架(Ruoyi Vue)
SimpleAdmin (new)
vboot-netmagic.net (Vue2.0)
网关采集系统(Blazor)
RuYiAdmin
CoreShop商城
Blog.Core
YuebonCore
企业级框架Furion
WebFirst
腾讯APIJSON.NET
WaterCloud微服务
ViperFamilyBucket应用框架通用后台
SmartSqlWMS仓库管理系统a
pevolo-apiFytSoaCms
开源项目地址:https://www.donet5.com/Home/Doc?typeId=1215
喜欢SqlSugar的可以在下面源码点个赞,点个关注
SqlSugar源码: https://github.com/DotNetNext/SqlSugar/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?