1.CodeFirst可以快速开发,使用起来也要分阶段使用,比如早期随便搞,中后期需要禁用一些功能保证数据安全(标题6和7 )
2.数据库账号需要有比较高的权限,
3.Sqlite不支持删除列和修改列只能添加列
会根据连接字符串中的数据库进行创建
//建库:如果不存在创建数据库存在不会重复创建 createdb db.DbMaintenance.CreateDatabase(); // 注意 :Oracle和个别国产库需不支持该方法,需要手动建库 //创建表:根据实体类CodeFirstTable1 (所有数据库都支持) db.CodeFirst.InitTables(typeof(CodeFirstTable1));//这样一个表就能成功创建了 //保护机质说明:如果不是sqlsugar建的表执行CodeFirst会报错看标题8 //实体定义看2.1
注意:默认类型是支持多种数据库的,能不设置尽量用自带的,ColumnDataType(想要多库兼容看4.2和9)一般用于特殊情况
public class CodeFirstTable1 { [SugarColumn(IsIdentity = true, IsPrimaryKey = true)] public int Id { get; set; } public string Name { get; set; } //ColumnDataType 一般用于单个库数据库,如果多库不建议用 [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)); /***批量创建表***/ //语法1: Type[] types= Assembly .LoadFrom("XXX.dll")//如果 .dll报错,可以换成 xxx.exe 有些生成的是exe .GetTypes().Where(it=>it.FullName.Contains("OrmTest."))//命名空间过滤,可以写其他条件 .ToArray();//断点调试一下是不是需要的Type,不是需要的在进行过滤 db.CodeFirst.SetStringDefaultLength(200).InitTables(types);//根据types创建表 //语法2: Type[] types= typeof(任意实体类中的类).Assembly.GetTypes() .Where(it=>it.FullName.Contains("OrmTest."))//命名空间过滤,当然你也可以写其他条件过滤 .ToArray(); db.CodeFirst.SetStringDefaultLength(200).InitTables(types);//根据types创建表
上面的例子需要加IsNullable=true才能实现创建可空类型,否则是必填类型
我们通过实体AOP配置 进行 自动 int? decimal?处理
var db = new SqlSugarClient(new ConnectionConfig() { DbType = SqlSugar.DbType.SqlServer, ConnectionString = Config.ConnectionString, IsAutoCloseConnection = true, ConfigureExternalServices = new ConfigureExternalServices { //注意: 这儿AOP设置不能少 EntityService = (c, p) => { /***低版本C#写法***/ // int? decimal?这种 isnullable=true 不支持string(下面.NET 7支持) if (p.IsPrimarykey==false&&c.PropertyType.IsGenericType && c.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) { p.IsNullable = true; } /***高版C#写法***/ //支持string?和string if(p.IsPrimarykey==false&&new NullabilityInfoContext() .Create(c).WriteState is NullabilityState.Nullable) { p.IsNullable = true; } } } }); //定义CodeFirst实体 public class xxxxx1 { //没有?是必填 [SugarColumn(IsIdentity = true, IsPrimaryKey = true)] public int id { get; set; } //老版本.NET字符串没办法加? 那就加特性[SugarColumn(IsNullable = true)] //如果不想用SugarColumn,AOP里面打个断点能进P.IsNullable=true说明就成功了 public string RequiredName { get; set; } //带?可空 public int? id1 { get; set; } }
通过实体AOP实现
SqlSugarClient db = new SqlSugarClient(new ConnectionConfig() { DbType = DbType.SqlServer, ConnectionString = Config.ConnectionString3, IsAutoCloseConnection = true, ConfigureExternalServices=new ConfigureExternalServices() { EntityService = (x,p) => //处理列名 { //最好排除DTO类 p.DbColumnName=UtilMethods.ToUnderLine(p.DbColumnName);//驼峰转下划线方法 }, EntityNameService = (x, p) => //处理表名 { //最好排除DTO类 p.DbTableName=UtilMethods.ToUnderLine(p.DbTableName);//驼峰转下划线方法 } } }); //表名mysql: test_name , oracle就是 TEST_NAME //public class TestName
想实体类干净可以用无特性写法,从用户使用情况来讲使用特性会更方便
SqlSugarClient 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(s).WriteState is NullabilityState.Nullable) { p.IsNullable = true; } } } }); //性能说明: //EntityService 相同实体只会执行一次性不需太操作
我们可以动态创建一个类来实现无实体建表
var typeBilder = db.DynamicBuilder().CreateClass("table1", new SugarTable(){}); //可以循环添加列 typeBilder.CreateProperty("Id",typeof(int),new SugarColumn(){IsPrimaryKey=true,IsIdentity=true}); typeBilder.CreateProperty("Name", typeof(string), new SugarColumn() { }); //SugarColumn 说明看标题4 //创建类 var type = typeBilder.BuilderType();//想缓存有typeBilder.WithCache //创建表 db.CodeFirst.InitTables(type); //建表属性API看迁移
如果想要增删查改可以看:https://www.donet5.com/Home/Doc?typeId=2562
简单的说就是通过修改实体后,在重新执行CodeFirst进行进行数据库表的修改
注意:正式数据一定要禁删除列操作,比如A用户实体因为没有同步少几个字段那么在CodeFirst就有删列风险
标题6或者7可以禁止删除列
功能 | 说明 |
添加列 | 在实体加添加属性 |
修改列 | 3种方式: 1、删除列执行CodeFirst后在添加列(兼容性好,缺点数据会消失) 2、更改类型,非空、长度 等执行CodeFirst【标题4有详细说明】 精度修改:默情况下decimal和double类型是不能修改精度的 我们可以启用精度修改配置 IsAutoCloseConnection = true, MoreSettings=new ConnMoreSettings() { EnableCodeFirstUpdatePrecision= true,//启用 //5.1.4.1.6-preview17+ } (缺点:特殊情况修改不了比如约束等,需要用方案1 或者手动改库) 3、修改列名保留数据【5.1有详细说明】 Sqlite不支持 修改 (官方没提供修改表的SQL语法) |
删除列 | 在实体删除属性 (标题6,7可以禁用) Sqlite 需要配置,需要升级到 5.1.4.118 - preview04+以上 IsAutoCloseConnection = true , DbType = DbType.Sqlite, ConnectionString = Connection, MoreSettings = new ConnMoreSettings()
SqliteCodeFirstEnableDropColumn = true } |
索引 | 特性设置索引就会建索引,只能手动删除索引【4.3有详细说明】 |
描述 | 表名和列都支持看文档 5.2 支持实体生成的XML备注,需要生成XML |
高安全级别:禁用更新 | 禁用后表结构不会发生变化 看档 6和7 |
高安全级别:手动对比迁移 | 纯手动去处理数据为变更 看文档10 |
[SugarTable("TableName")]//设置表名为TableName,如果不设置取类名为表名 public class CodeFirstTable { [SugarColumn(IsPrimaryKey = true)] public Guid Id { get; set; } public string name{get;set;} }
可一个实体建多个表
//新功能 5.0.2.3 db.CodeFirst.As<UnituLong>("UnituLong0011").InitTables<UnituLong>(); //该功能索引名要加占位符 //[SugarIndex("{table}index_codetable1_name",nameof(CodeFirstTable1.Name),OrderByType.Asc)] //老功能 var newTableName="Order_"+DateTime.Now.ToString("yyyyMMdd"); db.MappingTables.Add("Order", newTableName); // typeof(类).Name 可以拿到类名 db.CodeFirst.InitTables(typeof(Order)); //生成的表名是 newTableName
自动分表: http://www.donet5.com/Home/Doc?typeId=1201
名称 | 描述 |
---|---|
IsIdentity | 是否创建自增标识 |
IsPrimaryKey | 是否创建主键标识 |
ColumnName | 创建数据库字段的名称(默认取实体类属性名称) |
ColumnDataType | 创建数据库字段的类型 用法1: “varchar(20)” 不需要设置长度 用法2: 不设置该参数 系统会根据C#类型自动生成相应的数据库类型 用法3: 多库兼容 :标题4.2和标题9 |
IsIgnore | ORM不处理该列 |
ColumnDescription | 备注 表注释 新版本支持XML文件 , XML名字不要自已改要和类库名一样 把xml发布dll相同目录 |
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个 |
ExtendedAttribute | 扩展属性 ,可以结合EntityService 实体AOP使用 参考:https://www.donet5.com/ask/9/20054 |
如果大量使用 ColumnDataType="nvarchar(50)" 自定义类型将无法很好的支持多种数据库,比如很多库不支持nvarchar
当然你也可以使用AOP替换 ColumnDataType 去实现多库,下面介绍自带的方案
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 ,
} |
注意:该功能满足不了你可以看标题9
分表的用户注意了:请升级到5.0.8.6-preview03修复了分表问题
//普通索引(可以写多个) [SugarIndex("index_codetable1_name",nameof(CodeFirstTable1.Name),OrderByType.Asc)] //唯一索引 (true表示唯一索引 或者叫 唯一约束) [SugarIndex("unique_codetable1_CreateTime",nameof(CodeFirstTable1.CreateTime),OrderByType.Desc,true)] //复合普通索引 [SugarIndex("index_codetable1_nameid", nameof(CodeFirstTable1.Name), OrderByType.Asc, nameof(CodeFirstTable1.Id),OrderByType.Desc)] public class CodeFirstTable1 { [SugarColumn(IsIdentity = true, IsPrimaryKey = true)] public int Id { get; set; } public string Name { get; set; } [SugarColumn(ColumnDataType = "Nvarchar(255)")]//custom public string Text { get; set; } [SugarColumn(IsNullable = true)] public DateTime CreateTime { get; set; } } //分表的用户注意了:请升级到5.0.8.6-preview03修复了分表问题
给索引名添加占位符
//占位符 普通表:{table} 分表:{split_table} 数据库{db} //请升级到 5.0.2.3preivew04 //使用 {db} 进行占位符替换,小写不要有空格 [SugarIndex("{db}index_codetable1_name",nameof(CodeFirstTable1.Name),OrderByType.Asc)] //普通表名占位符 [SugarIndex("index_{table}_name",nameof(CodeFirstTable1.Name),OrderByType.Asc)] //分表占位符需5.1.4.140,老版本可以不加占位符只是格式不能自定义 [SugarIndex("index_{split_table}_name",nameof(CodeFirstTable1.Name),OrderByType.Asc)]
索引include 5.1.3.31-preview11
//不要有空格并且小写等于 include(name,id) [SugarIndex("IndexUnituadfasf1_longx{include:name,id}", nameof(longx), OrderByType.Asc)] public class Unituadfasf1 { public ulong longx { get; set; } public int id { get; set; } public string name { get; set; } }
注意1:属性随便写个名字不按规范写就会删掉在创建
注意2:Sqlite不支持修改列操作
注意3: 表特性如果有禁止修改 要先去掉
[SugarColumn( OldColumnName ="Name")] public string NewName { get; set; }
如果不写特性也可以用XML自动读取备注生成XML(注意:xml名字不要改要和类库名一模一样)
db.CodeFirst.InitTables(typeof(CodeFirstTable)); [SugarTable("CodeFirstTable2",TableDescription = "表备注")]//表添加备注 public class CodeFirstTable { [SugarColumn(IsPrimaryKey = true, ColumnDescription="主键")]//列添加备注 public Guid Id { get; set; } } //技巧:表名可以为null,这样就会取实体名 [SugarTable(null,TableDescription = "表备注")]//表添加备注
对性能要求高的可以禁用XML方式读取备注
默认是先读特性没有备注在读XML
IsAutoCloseConnection = true, DbType = DbType.SqlServer, ConnectionString = Connection, LanguageType=LanguageType.Default, MoreSettings=new ConnMoreSettings() { //禁用掉提升初始化第一次性能 IsNoReadXmlDescription=true//禁止读取XML中备注,true是禁用 } //禁用掉xml只能通过特性写备注 [SugarTable("CodeFirstTable2",TableDescription = "表备注")] [SugarColumn( ColumnDescription="主键")]//列添加备注
注意:Sqlite本身就不支持删除列 可以不设置
如果实体类中属性给删掉在执行InitTables那么数据库中的列也会删除,为了避免误操作把列删掉。下面支持了禁止删除列
禁止删列:
设置成下面的写法 就不会自动删除列了
[SugarTable("Custom","客户",IsDisabledDelete =true)] public class Custom { public int Id { get; set; } public string Name { get; set; } }
全局AOP全部禁止
DbType = SqlSugar.DbType.PostgreSQL, ConnectionString = Config.ConnectionString, ConfigureExternalServices=new ConfigureExternalServices() { EntityNameService = (type, entity) => { entity.IsDisabledDelete = true; } }
这样设置后会大大提高CodeFirst的执行性能,因为不用去检查实体数据库变化,也不会更新数据库
IsDisabledUpdateAll=true 那么表存在就不会在执行任何更新操作
[SugarTable("Custom","客户",IsDisabledUpdateAll=true)]//安全级别比 IsDisabledDelete 更高,只创建不修改和删除 public class Custom { public int Id { get; set; } public string Name { get; set; } } db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(Custom)); //注意这行代码加的 //上面配置等同于 //if(表不存在) //{ // db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(Custom)); ///}
默认会报错的也算是一个保护机质,让你无法更新不是SQLSUGAR建的表,有2种方法解决
1.你可以试着把非SQLSUGAR建的表主键约束删掉在试试,如果还不行就说明不能更新,如果没有重要数据就把表删了在建吧
2.也可以禁用更新这个张表
[SugarTable("Custom","客户",IsDisabledUpdateAll=true)]//IsDisabledUpdateAll表示不更新这个表
注意:先看标题4.2如果不能满足我们可以使用AOP动态处理
注意:先看标题4.2如果不能满足我们可以使用AOP动态处理
注意:先看标题4.2如果不能满足我们可以使用AOP动态处理
如果使用自定义类型我们就需要向下面这么写
[SugarColumn(ColumnDataType = "varchar(max)")]
上面的只支持sqlserver(max mysql不支持)下面我们来兼容mysql
var db = new SqlSugarClient(new ConnectionConfig() { DbType = SqlSugar.DbType.SqlServer, ConnectionString = Config.ConnectionString, IsAutoCloseConnection = true, ConfigureExternalServices = new ConfigureExternalServices { EntityService = (c, p) => { //4.2有介绍多库的大文本,这儿只是示例讲解怎么用AOP if (type==DbType.MySql&&p.DataType=="varchar(max)") { p.DataType = "longtext"; } } } });
该功能适合成熟,线上稳定的项目,这样不会去自动通过实体修改表结构,而是手工处理
新功能:5.0.5.8 preview02
Type [] types= xxxx; var diffString= db.CodeFirst.GetDifferenceTables(types).ToDiffString();
我们可以通过结构对比拿到差异信息
根据这些信息我们可以手动去库里面更改
数据安全多重保险:
定义2个接口一个接调用对比方法
var diffString= db.CodeFirst.GetDifferenceTables(types).ToDiffString()
第二个接口调用更新
db.CodeFirst.InitTables(types);
更新前先调用对比接口比较一下,修改是不是符合要求,符合要求在执行更新接口。
如果有时间可以做成一个界面,这样点更新先弹出对比结果,然后在点更新更新库
这种方式是不是比脚本维护起来更方便呢。
在不设置排序是按实体类顺序进行创建表,特殊情况下手动进行排序
规则说明
1、主键反无论设置不设置都是第1位
2、如果不设默认为0
3、如果想只设置一个字段的情况想排前面 可以设置-1 这种负数,默认为0
5.0.9.6版本
[SqlSugar.SugarTable("Custom", IsCreateTableFiledSort =true)]//开启排序不能少 public class Custom { [SqlSugar.SugarColumn(CreateTableFieldSort = 1)] public int Id { get; set; } [SqlSugar.SugarColumn( CreateTableFieldSort =2)] public string Name { get; set; } }
注意:默认是0,可以用-1排前面
需要先学习多租户
//根据特性标识哪个库 (需要高版本才支持) db.CodeFirst.InitTablesWithAttr(new[] { typeof(UserInfo001), typeof(UserInfo002) }); //指定库 db.GetConnection("id").CodeFirst.InitTables(new[] { typeof(UserInfo001), typeof(UserInfo002) });
2016 © donet5.comApache Licence 2.0