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();
//一对多用:OneToManyEnableLogicDeletepublic 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方法();
};需要升级到:SqlSugarCore 5.1.4.188-preview10 +
[Navigate(NavigateType.OneToMany, nameof(AxisPosition.AxisId))]
public ObservableCollection<AxisPosition> AxisPositions //例如这样非标准LIST
{
get => _axisPositions;
set => SetProperty(ref _axisPositions, value);
}
SqlSugarHelper.DB.UpdateNav<Axis>(Axes)
.Include(z => z.AxisPositions.ToList())//需要加一个ToList
.ExecuteCommand();
//SqlSugarCore 5.1.4.188-preview10 +多个共用一个对象的情况 ,一般前端传过来序列化的都是OK的。一般是查询出来在组装的会出现这种情况。
var tasks = db.Queryable<RatingTask>()
.Where(t => t.Id == 1 || t.Id == 2)
.ToList();
List<RatingTaskEmp> emps = [new RatingTaskEmp { EmpId = 101, EmpName = "张三",},
new RatingTaskEmp { EmpId = 102, EmpName = "李四", },];
foreach (var task in tasks)
{
task.EmpList = emps;//多个共用一个对象的情况
}
//需要将Task.EmpList都变成新对象
//可以用
var tasks=db.Utilities.TranslateCopy(tasks):
//对性能要求高的可以用AutoMapper等工具导航更新: 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