导航更新、级联保存

与EF CORE区别

SqlSugar不依赖数据库外键,只要配置实体导航就能使用

注意事项

long的主键会用雪花ID自动填充,可以用外部雪花ID标题7,  一定要设置WORKID , 只要静态变量不能共享的情况都要有独的WorkId

比如我本地插入和服务上插入那么在同一时间可能会有重复

比如我负载多个服务器时候

SnowFlakeSingle.WorkId= 唯一数字; //从配置文件读取一定要不一样
//在程序启动时设置一次就行


1、导航更新语法(多层级)

设计参考于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(..)


2、性能介绍

主键自增性能最差,因为自增需要循环才能拿到(多对多中间表除外

如果是自增建议小数据更新


3、一对一

 3.1 逻辑

逻辑更新主表 ,子表存在更新,不存在插入

 3.2 用例

//实体
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();


4、一对多

 4.1 逻辑

先更新主表然后 删除子表 在 插入子表

 4.2 用例

//实体
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();//

5、多对多

 5.1 逻辑

有4种模式 ,A表代表主表,B表代表从表

1、只更新关系表 

2、更新A表+关系表 

3、更新B表+关系表,

4、更新A表、B表和关系表

 5.2 用例

//实体
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();

 5.3 中间额外字段赋值

假设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.4 多对多假删除

5.1.4.89-preview10

 db.UpdateNav(list)
    .Include(z1 => z1.BList,new UpdateNavOptions { 
            ManyToManyEnableLogicDelete=true //需要结合过滤器实现假删
             })
            .ExecuteCommand();
            //一对多用:OneToManyEnableLogicDelete


6、主表通用功能

 6.1 IgnoreColumns    忽略更新列

 6.2  UpdateColumns 只更新列

 6.3  可以插入主表 (插或更新)

配置IsInsertRoot那么主表不存在就插入存在更新

db.UpdateNav(list,new UpdateNavRootOptions()
{
    IsInsertRoot = true
})
.Include(x => x.Roles).ExecuteCommand();

 6.4 IsDiffLogEvent 差异日

 6.5  禁止更新主表 

 6.7 IsOptLock  乐观锁

具体用法如下

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 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();

 6.8 添加委托

5.1.2.5-preview03

比如我想添加忽略列,想用Updateable的方法

 Expression<Action<IUpdateable<Student_004>>> rootFunc = it => it.IgnoreColumns(x => x.Name);//不更新name委托

 db.UpdateNav(list)
          .Include(x=>x.books,new UpdateNavOptions() { 
                     RootFunc = rootFunc,//给List加委托 ,多个Inclue只要写第一个
                    //CurrentFunc = 当前Include x.Books 加委托,
                }).ExecuteCommand();


7、雪花ID冲突

导航更新默认是自带的雪花ID,如果和你的代码中的雪花ID冲突了可以全部替换成你的雪花ID

  //程序启动时执行一次就行
  StaticConfig.CustomSnowFlakeFunc = () =>
  {
      return 你的雪花ID方法();
  };



8、更多导航操作

导航更新: 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


关闭
文档:SqlSugar5.0