SqlSugar不依赖数据库外键,只要配置实体导航就能使用
注意事项
long的主键会用雪花ID自动填充,可以用外部雪花ID标题8, 一定要设置WORKID , 只要静态变量不能共享的情况都要有独的WorkId
比如我本地插入和服务上插入那么在同一时间可能会有重复
比如我负载多个服务器时候
SnowFlakeSingle.WorkId= 唯一数字; //从配置文件读取一定要不一样 //在程序启动时设置一次就行
设计参考于EF Core查询,只要配置好实体就可以随意使用导航进行插入操作
//说明: 一对一 、一对多和多对多都可以混合使用 //list里面是多层级的对象 List<Student> list=new List<Student>(); list.Add(new Student(){ Id=1, Name="jack", SchoolId=2, SchoolA=new SchoolA(){...RoomList=new List<Room>{...}}, Books=new List<Books> {...} }) db.UpdateNav(list) .Include(z1 => z1.SchoolA).ThenInclude(z1 => z1.RoomList)//更新2层 Root->ShoolA-RoomList .Include(z1 => z1.Books)//更新第1层 Root->Books .ExecuteCommand(); //这种表示多层级 //Include(..).ThenInclude(..).ThenInclude(..)
主键自增性能最差,因为自增需要循环才能拿到(多对多中间表除外)
如果是自增建议小数据更新
逻辑更新主表 ,子表存在更新,不存在插入
//实体 public class StudentA { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int StudentId { get; set; } public string Name { get; set; } public int SchoolId { get; set; } //标准配置 推荐 [Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一对一 SchoolId是StudentA类里面的 public SchoolA SchoolA { get; set; } //不能赋值只能是null //非主键模式 需要手动赋值防止插入0这种默认值 //[Navigate(NavigateType.OneToOne, nameof(SchoolId),nameof(SchoolA.Id))] } public class SchoolA { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id{ get; set; } public string SchoolName { get; set; } } //逻辑更新主表 ,子表存在更新,不存在插入 var List<StudentA> list=new List<StudentA>(){....}; db.UpdateNav(List<StudentA>) .Include(z1 => z1.SchoolA) .ExecuteCommand();
请升级到:5.1.4.111-preview15+才支持
更新的时候SchoolId =0只给SchoolA中主键赋值
var StudentA=new StudentA() { Id=1, Name="张三", SchoolId =4,//如果这个ID=4数据库中不存在只要有这可能性 全部强制改成默认值0 (int默认值是0) SchoolA=new SchoolA() { Id=1 //这边赋值正确值就行,存在更新不存在插入 Name="北大" } } //需要升级到:5.1.4.111-preview15 才支持这种兼容错误数据
注意:这种一般发生在带有脏数据的情况,比如删掉了子表中的记录,而主表还存在这个记录,并且又UI操作,UI可能会强制让你选
先用默认的,不满足需求在看这个
db.UpdateNav(data, new UpdateNavRootOptions() { IsInsertRoot = true//主表启用插入或者更新 }) .ThenInclude(n => n.SchoolA, new UpdateNavOptions() { //强制按主键实现插入或者更新 //5.1.4.157-preview11+ OneToOneSaveByPrimaryKey = true }) .ExecuteCommand()
先更新主表然后 删除子表 在 插入子表
优点:这种性能好在乎性能的推荐这种 (推荐)
db.UpdateNav(list) .Include(x => x.Persons)//默认 .ExecuteCommand();
请升级到:5.1.4.113-preview+
先更新主表 子表存在更新 、不存在插入 同时 也支持前端删掉子表
优点:减少了删除操作
缺点:因为前端本身就有删除操作所以存在插入、改和删3种逻辑 性能比4.1要差一点
db.UpdateNav(list2) .Include(x => x.Persons,new SqlSugar.UpdateNavOptions() { OneToManyInsertOrUpdate = true,//配置启用 插入、更新或删除模式 }) .ExecuteCommand(); //请升级到:5.1.4.113-preview+
注意:想走更新逻辑需要主键 ,如果没主键就当作前端删掉在加
//实体 public class StudentA { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id{ get; set; } public string Name { get; set; } public int SchoolId { get; set; } [Navigate(NavigateType.OneToMany, nameof(BookA.studenId))]//BookA表中的studenId public List<BookA> Books { get; set; }//注意禁止给books手动赋值 //非主键模式 需要手动赋值防止插入0这种默认值 //[Navigate(NavigateType.OneToMany, nameof(BookA.studenId),nameof(Id))] //与一对一相反 第一个 从表字段,第二个主表字段 } public class BookA { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int BookId { get; set; } public string Name { get; set; } public int studenId { get; set; } } //先更新主表然后 删除子表 在 插入子表 var List<StudentA> list=new List<StudentA>(){....}; db.UpdateNav(list) .Include(z1 => z1.Books) .ExecuteCommand(); //强制删除下级一对多脏数据(5.0.2.3-preview04) db.UpdateNav(list) .Include(z1 => z1.Books,new UpdateNavOptions(){OneToManyDeleteAll=true})//强制删除下级一对多的脏数据 .ThenInclude(z1 => z1.RoomList) .ExecuteCommand(); //只更新子表 db.UpdateNav(list,new UpdateNavRootOptions(){ IsDisableUpdateRoot= true}) .Include(x => x.datas).ExecuteCommand(); //假删除(5.1.4.86) db.QueryFilter.AddTableFilter<Province>(it => it.IsDeleted == false);//配合查询过滤器 db.UpdateNav(country) .Include(it => it.Provinces,new UpdateNavOptions() { OneToManyEnableLogicDelete=true }) .ExecuteCommand();// //null列不更新5.1.144-preview13+ db.UpdateNav(list) .Include(x => x.Books, new SqlSugar.UpdateNavOptions() { OneToManyInsertOrUpdate = true, IgnoreNullColumns=true }).ExecuteCommand(); //忽略列不更新 db.UpdateNav(list) .Include(x => x.Books, new SqlSugar.UpdateNavOptions() { OneToManyInsertOrUpdate = true, IgnoreColumns =new string[] { "Name" } }).ExecuteCommand();
有4种模式 ,A表代表主表,B表代表从表
1、只更新关系表
2、更新A表+关系表
3、更新B表+关系表,
4、更新A表、B表和关系表
//实体 public class ABMapping1 { [SugarColumn(IsPrimaryKey = true)]//中间表可以不是主键 public int AId { get; set; } [SugarColumn(IsPrimaryKey = true)]//中间表可以不是主键 public int BId { get; set; } } public class A1 { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } public string Name { get; set; } [Navigate(typeof(ABMapping1), nameof(ABMapping1.AId), nameof(ABMapping1.BId))]//注意顺序 public List<B1> BList { get; set; }//只能是null不能赋默认值 } public class B1 { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } public string Name { get; set; } [Navigat(typeof(ABMapping1), nameof(ABMapping1.BId), nameof(ABMapping1.AId))]//注意顺序 public List<A1> AList { get; set; }//只能是null不能赋默认值 } List<A1> List=new List<A1>{ new A1(){ Id=1,BList=new List<B1>{...}} }; //默认模式:只更新关系表 (删除添加) db.UpdateNav(list) .Include(z1 => z1.BList) .ExecuteCommand();//技巧:只更新中间表可以只传A和B表的主键其他不用赋值 //更新A表+更新关系表 db.UpdateNav(list) .Include(z1 => z1.BList,new UpdateNavOptions { ManyToManyIsUpdateA=true }) .ExecuteCommand(); //不存在添加B表,存在更新B表 + 更新关系 db.UpdateNav(list) .Include(z1 => z1.BList,new UpdateNavOptions { ManyToManyIsUpdateB=true }) .ExecuteCommand(); //更新A表 + 不存在添加B表,存在更新B表 + 更新关系 db.UpdateNav(list) .Include(z1 => z1.BList,new UpdateNavOptions { ManyToManyIsUpdateA=true ManyToManyIsUpdateB=true }) .ExecuteCommand();
假设Opt 为A表 ,Roles为B表 ,OptRole为中间表 请升级:5.1.4.86
db.UpdateNav(Opt).Include(z => z.Roles, new UpdateNavOptions() { //设置中间表其他字段 (5.1.4.86) ManyToManySaveMappingTemplate = new OptRole() { CreateTime = "1010",//除了主键和Aid和Bid外的字段赋值 OrgId = "1x" } }) .ExecuteCommand();
5.1.4.89-preview10
db.UpdateNav(list) .Include(z1 => z1.BList,new UpdateNavOptions { ManyToManyEnableLogicDelete=true //需要结合过滤器实现假删 }) .ExecuteCommand(); //一对多用:OneToManyEnableLogicDelete
public class UpdateNavRootOptions { public string[] IgnoreColumns { get; set; }//主表更新忽略列(实体配置特性也可以方便的实现) public string[] UpdateColumns { get; set; }//只更新哪几列 public bool IsInsertRoot { get; set; }//强制插入主表 可以实现 更新或者插入效果 public string[] IgnoreInsertColumns { get; set; }//主表启用插入忽略列 5.1.3.58 public bool IsIgnoreAllNullColumns {get;set;} //不更新null列 5.1.4.112 public bool IsDiffLogEvent { get; set; }//启用主表差异日志 public object DiffLogBizData { get; set; }//差异日志参数 public bool IsDisableUpdateRoot { get; set; }//禁更新主表5.1.3.33-preview05 public bool IsOptLock{get;set;}//主表乐观锁 5.1.4.90 } //使用示例 db.UpdateNav(list,new UpdateNavRootOptions() { IgnoreColumns = new string[] { "Id" } }) .Include(x => x.Roles).ExecuteCommand();
db.UpdateNav(list,new UpdateNavRootOptions() { IgnoreColumns = new string[] {"Name","CreateTime"}// 主表这2列不更新 }) .Include(x => x.Roles).ExecuteCommand();
db.UpdateNav(list,new UpdateNavRootOptions() { UpdateColumns = new string[]{"Name","CreateTime"}//主表只更新2列 }) .Include(x => x.Roles).ExecuteCommand();
配置IsInsertRoot那么主表不存在就插入存在更新
db.UpdateNav(list,new UpdateNavRootOptions() { IsInsertRoot = true }) .Include(x => x.Roles).ExecuteCommand();
db.UpdateNav(list,new UpdateNavRootOptions() { IsDiffLogEvent = true 主表启用差异日志 //DiffLogBizData }) .Include(x => x.Roles).ExecuteCommand();
db.UpdateNav(list,new UpdateNavRootOptions() { IsDisableUpdateRoot=true //主表不更新 }) .Include(x => x.Roles).ExecuteCommand();
db.UpdateNav(list,new UpdateNavRootOptions() { IsOptLock = true//主表启用乐观锁 }) .Include(x => x.Roles).ExecuteCommand();
db.UpdateNav(list,new UpdateNavRootOptions() { IsIgnoreAllNullColumns=true//主表null列不更新 }) .Include(x => x.Roles).ExecuteCommand();
新功能:5.1.4.108
支持第2层级的所有导航自动Includes (超过2层的需要用手动导航更新)
db.UpdateNav(list).IncludesAllFirstLayer().ExecuteCommand(); db.UpdateNav(list).IncludesAllFirstLayer(nameof(类.导航),nameof(类.导航2)).ExecuteCommand();//排除不需要的导航 //3级+自动 db.UpdateNav(list) .IncludesAllFirstLayer()//自动2级 .IncludeByNameString(nameof(类.导航)).ThenIncludeByNameString(nameof(类.导航2))//3级 .ExecuteCommand();
自动导航 这个看不懂?可以看导航插入 有详细的例子原理一样
导航更新默认是自带的雪花ID,如果和你的代码中的雪花ID冲突了可以全部替换成你的雪花ID
//程序启动时执行一次就行 StaticConfig.CustomSnowFlakeFunc = () => { return 你的雪花ID方法(); };
导航更新: https://www.donet5.com/home/Doc?typeId=2432
导航删除: https://www.donet5.com/home/Doc?typeId=2431
导航插入: https://www.donet5.com/home/Doc?typeId=2430
导航查询: https://www.donet5.com/home/Doc?typeId=1188
2016 © donet5.comApache Licence 2.0