【导航查询】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列
- 【开篇】.NET开源 ORM 框架 SqlSugar 系列
- 【入门必看】.NET开源 ORM 框架 SqlSugar 系列
- 【实体配置】.NET开源 ORM 框架 SqlSugar 系列
- 【Db First】.NET开源 ORM 框架 SqlSugar 系列
- 【Code First】.NET开源 ORM 框架 SqlSugar 系列
- 【数据事务】.NET开源 ORM 框架 SqlSugar 系列
- 【连接池】.NET开源 ORM 框架 SqlSugar 系列
- 【查询目录】.NET开源 ORM 框架 SqlSugar 系列
- 【查询基础】.NET开源 ORM 框架 SqlSugar 系列
- 【排序用法】.NET开源 ORM 框架 SqlSugar 系列
- 【分组去重】.NET开源 ORM 框架 SqlSugar 系列
- 【联表查询】.NET开源 ORM 框架 SqlSugar 系列
- 【导航查询】.NET开源 ORM 框架 SqlSugar 系列
- 【子查询】.NET开源 ORM 框架 SqlSugar 系列
- 【嵌套查询】.NET开源 ORM 框架 SqlSugar 系列
💦万丈高楼平地起,做开发想要技术精进,必须要有扎实的基础功底。基础SQL查询语法一定要牢记于心,才能应对后面更为复杂的形势。
1、导航查询特点
💥作用:主要处理主对象里面有子对象这种层级关系查询
1.1 无外键开箱就用
其它ORM导航查询 需要 各种配置或者外键,而 SqlSugar 则开箱就用,无外键,只需配置特性和主键就能使用
1.2 高性能优
查询 性能非常强悍 5.0.8.1+版本进行了性能优化
支持大数据分页导航查询
3.3 语法超级爽
var list=db.Queryable<Test>().Includes(t=> t.Provinces, pro=>pro.Citys ,cit=>cit.Street) //多层级.Includes(t=> t.ClassInfo)// 一个层级查询.ToList(); //具体用法看下面文档介绍//多层级可以看2.5
2、新导航查询
适合有主键的常规操作, 请升级到5.0.6.8
2.1.1 一对一 ( one to one )
//实体
public class StudentA
{[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]public int StudentId { get; set; }public string Name { get; set; }public string SexCode { get;set;}public int SchoolId { get; set; }//用例1:主键模式 StudentA(主表)表中的 SchoolId 和SchoolA(子表)中的主键关联 [Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一对一 SchoolId是StudentA类里面的public SchoolA SchoolA { get; set; } //不能赋值只能是null//用例2:反向导航,2个字段匹配关系 [Navigate(NavigateType.OneToOne,nameof(SchoolId),nameof(SchoolA.Id))]//变量名不要等类名 public SchoolA SchoolItem { get; set; } //不能赋值只能是null//第一个主表字段,第二从表字段 顺序不要错了//用例3: 字典导航 多了个SQL条件参数 //[SqlSugar.Navigate(NavigateType.OneToOne,nameof(SexId),nameof(DataDictionary1.Code),"type='sex'")]//具体用法可以看配置查询 https://www.donet5.com/Home/Doc?typeId=2309}
public class SchoolA
{[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]public int Id{ get; set; }public string SchoolName { get; set; }
} //导航+主表过滤 导航属性过滤
var list = db.Queryable<StudentA>().Includes(x => x.SchoolA) //填充子对象 (不填充可以不写).Where(x =>x.SchoolA.SchoolName=="北大") .ToList();//导航+主表过滤 只查有导航数据 (新功能:5.1.2.8)
var list = db.Queryable<StudentA>().Includes(x => x.SchoolA) //填充子对象 (不填充可以不写).Where(x => SqlFunc.Exists(x.SchoolA.主键)).ToList(); //导航+子表过滤 5.0.9.4-preview06 请注意升级
//创建一个扩展函数,默认是Class不支持Where
public static List<T> Where<T>(this T thisValue, Func<T,bool> whereExpression ) where T:class,new()
{return new List<T>() { thisValue };
}
var list = db.Queryable<Student_003>().Includes(x => x.school_001.Where(z=>z.Name=="a").ToList())//扩展的Where对子表进行过滤.ToList(); //5.0.9.4-preview06 才支持 请注意升级 请注意升级//导航 指定字段 5.1.3.38
var list = db.Queryable<StudentA>().Includes(x => x.SchoolA.ToList(it=>new SchoolA(){ Name =it.Name,id=it.Id})) .ToList(); //只查一个字段写法1:
var list = db.Queryable<StudentA>().Where(x => x.id>1) //Where和Select中别名要写一样.Select(x =>new { x=x,SchoolName= x.SchoolA.SchoolName}).ToList();//只查一个字段写法2:
[Navigate(NavigateType.OneToOne, nameof(SchoolId))]
public SchoolA SchoolA { get; set; }
[SugarColumn(IsIgnore=true)]//加IsIgnore
public string SchoolName{get=>this.SchoolA?.Name;}//?防止空引用
多字段1对1 看文档2.4
2.1.2 多对一 (many to oney)
多对一其实就是一对一,用法上差不多,只是多了一个参数
//第一个参数:当前表字段 //第二个参数: 子表中字段[Navigate(NavigateType.OneToOne,nameof(WorkOrderId),nameof(Wo.Id))]public Wo Wo { get; set; }//不要给get set赋值//也可以这样[Navigate(NavigateType.ManyToOne,nameof(WorkOrderId),nameof(Wo.Id))]public Wo Wo { get; set; }//不要给get set赋值
用法:看一对一的教程就行了
2.2 一对多 ( one to many)
BookA(子表)中的 studenId 和 StudentA(主表)中的主键关联
//实体
public class StudentA
{[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]public int Id{ get; set; }public string Name { get; set; }public int SchoolId { get; set; }//用例1:正常一对多[Navigate(NavigateType.OneToMany, nameof(BookA.studenId))]//BookA表中的studenIdpublic List<BookA> Books { get; set; }//注意禁止给books手动赋值//用例2:反向导航支持:StudentA没有主键或者指定关系[Navigate(NavigateType.OneToMany, nameof(BookA.studenId),nameof(Id))] public List<BookA> Books { get; set; }//注意禁止给books手动赋值//与一对一相反 第一个 从表字段,第二个主表字段}
public class BookA
{[SugarColumn(IsPrimaryKey = true, IsIdentity = true)]public int BookId { get; set; }public string Name { get; set; }public int studenId { get; set; }
}//例1:简单用法
var list = db.Queryable<StudentA>()
.Includes(x => x.Books)
.ToList();//例2:支持Any和Count 对主表进行过滤 (子对象过滤看下面)
var list = db.Queryable<StudentA>()
.Includes(x => x.Books)
.Where(x => x.Books.Any())
//带条件的
//.Where(x => x.Books.Any(z=>z.Name=="jack")))
.ToList();//例3: 没有Includes也可以使用过滤
var list2 = db.Queryable<StudentA>()
.Where(x => x.Books.Any())//Any中可以加条件 Any(z=>z.BookId==1)
.ToList(); //例4 Where子对象进行排序和过滤 (支持WhereIF)
var list = db.Queryable<StudentA>().Includes(x => x.Books.Where(y => y.BookId > 0).OrderBy(y => y.BookId).ToList()).ToList();//例5 主表+子表都过滤
var list = db.Queryable<StudentA>()
.Includes(x => x.Books.Where(it=>it.Name=="jack").ToList())//只过滤子表
.Where(x => x.Books.Any(z=>z.Name=="jack")))//通过子表过滤主表
.ToList();//例6:Select指定字段
var list= db.Queryable<StudentA>().Includes(x => x.Books.Select(z=>new BookA() { Names = z.Names }).ToList()) //例7:Select多层级 (结构:StudentAt->books->BookItems)
var list= db.Queryable<StudentA>().Includes(x => x.Books.Select(z=>new BookA(){Names=z.Name}.ToList(),it=>BookItems)) .ToList();、//Includes中的Select只能是字段 ,不能导航对象 //例8:OrderBy指定字段 (Skip Take可以分页)
var list= db.Queryable<StudentA>().Includes(x => x.Books.OrderBy(z=>z.Id).ToList()) .ToList();//例9:Take取前几条
var list= db.Queryable<StudentA>().Includes(x => x.Books.Take(10).ToList()) .ToList(); //例10:DTO支持进行了强化
看标题2.7 //例11:一对多后还可用追加字段映射MappingField 如果以前是1个字关联,现在追加后就成了1+1
db.Queryable<StudentA>().Includes(x => x.Books.MappingField(z=>z.字段,()=>x.字段).ToList() ).ToList();
//MappingField 和 Where区别
//MappingField MappingField用来指定2个对象的关系,Where只能当前表过滤不能和主表进行关联
//MappingField 可以多个也可以和Where一起始用
非标准1对多 看文档2.4
2.3 多对多 ( many to many)
//实体
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; }[Navigate(typeof(ABMapping1), nameof(ABMapping1.BId), nameof(ABMapping1.AId))]//注意顺序public List<A1> AList { get; set; }//只能是null不能赋默认值
}
//例1:简单用法 直接填充B的集合,只要配置好特性非常简单
var list3= db.Queryable<A1>().Includes(x => x.BList).ToList(); //例2:支持子对象排序和过滤 (支持WhereIF)
var list3= db.Queryable<A1>().Includes(x => x.BList.Where(z=>z.Id>0).ToList()).ToList(); //例3:支持主表过滤 Any和Count
var list3= db.Queryable<A1>().Includes(x => x.BList).Where(x=>x.BList.Any())//Any里面可以加条件 Any(z=>z.xxxx>0).ToList();//例4主表+子表都过滤
var list = db.Queryable<StudentA>().Includes(x => x.BList.Where(it=>it.Name=="jack").ToList())//只过滤子表.Where(x => x.BList.Any(z=>z.Name=="jack")))//通过子表过滤主表.ToList(); //不使用Includes一样可以过滤
var list3= db.Queryable<A1>() .Where(x=>x.BList.Any()) //可以加条件.Where(x=>x.BList.Any(z=>z.xxx==x.yyy)).ToList(); //A表和B表不是主键情况多了2个参数
//升级到: SqlSugarCore 5.1.4.147-preview16+
[Navigate(typeof(OptRole), nameof(OptRole.operId), //中间表 aidnameof(OptRole.roleId),//中间表 bidnameof(OperatorInfo.id),//a表 idnameof(Role.id2))] //b表idpublic List<Role> Roles { get; set; }//四参数重载只支持查询
2.4 多字段关系映射
支持多个字段关联 5.1.4.108-preview32 (可以是N个)
var list=db.Queryable<UnitAddress011>().Includes(x => x.Persons).ToList();//m是主表字段 c是子表字段 是一个json数组 格式不要错了
[Navigate(NavigateType.Dynamic, "[{m:\"Id\",c:\"AddressId\"},{m:\"Id2\",c:\"AddressId2\"}]")]
public List<UnitPerson011> Persons { get; set; }
💥注意:该功能只能用在查询上,能用正常导航就尽量使用正常导航
2.5 多级导航
配置好实体类,我们可以多级查询(一对多、一对多、多对多都支持只要配好类就可以使用)
public class StudentA
{[SugarColumn(IsPrimaryKey = true)]public int StudentId { get; set; }public string Name { get; set; }public int SchoolId { get; set; }[Navigate(NavigateType.OneToOne, nameof(SchoolId))]//一对一public SchoolA SchoolA { get; set; }[Navigate(NavigateType.OneToMany, nameof(BookA.studenId))]//一对多public List<BookA> Books { get; set; }//只能是null不能赋默认值}
public class SchoolA
{[SugarColumn(IsPrimaryKey = true)]public int SchoolId { get; set; }public string SchoolName { get; set; }[Navigate(NavigateType.OneToMany, nameof(RoomA.SchoolId))]//一对多public List<RoomA> RoomList { get; set; }//只能是null不能赋默认值
}public class RoomA
{[SugarColumn(IsPrimaryKey = true)]public int RoomId { get; set; }public string RoomName { get; set; }public int SchoolId { get; set; }
}
public class BookA
{[SugarColumn(IsPrimaryKey = true)]public int BookId { get; set; }public string Name { get; set; }public int studenId { get; set; }
} var list2 = db.Queryable<StudentA>()//查2层.Includes(st => st.SchoolA, sch=> sch.RoomList)//查询2级(等于EF ThenInclude)//查1层.Includes(st=> st.Books) .ToList()
//说明: 一对多 多对多 一对多 只要配好了都可以多层级使用//如果想超过3个层级需要.AsNavQueryable()
//缺点VS提示会消失,直接写不要在乎意提示不出来,VS关掉在开就行了,只要不改这个代码提示就不会有问题
db.Queryable<Order>()Includes(it=>it.xx).AsNavQueryable()//加这个前面.Includes(it=>it.1,it=>it.2,it=>it.3,it=>it.4,it=>it.5..)
//.AsNavQueryable()能不用尽量不要用,正常Includes(+3)重载完全够用了
2.6 性能优化
1、升级 如果搜索不到勾选预览版本
5.0.8.1 + 版本针对大数据导航有了很好的性能优化
5.1.4.159 +又进行了一次优化 ,主表一次查一万以上建议升级
2、老版本优化方案
底层分批量查询 适合一次性查询 1000 条以上的导航
var list = new List<Tree1>();db.Queryable<Tree1>().Includes(it => it.Child).ForEach(it => list.Add(it), 300); //每次查询300条
3、关联字段推荐用主键,如果非主键导航加索引为佳
2.7 转DTO (必学的技巧)
1. 自动DTO (推荐 )
//Mapster 工具映射 (推荐) 比AutoMapper方便不需要配置
//Nuget直接安装就行了//简单示例:结构一样直接转换
var list=db.Queryable<StudentA>().Includes(x => x.Books).ToList();
var dtoList=list.Adapt<List<StudentDTO>>()//技巧示例:这个用法必学通过规则映射DTOpublic class TreeDTO{public int Id { get; set; }public string Name { get; set; }public int ParentId { get; set; }public string ParentName { get; set; }//对应Parent中的Name}
public class Tree{[SqlSugar.SugarColumn(IsPrimaryKey = true)]public int Id { get; set; }public string Name { get; set; }public int ParentId { get; set; }[Navigate(NavigateType.OneToOne,nameof(ParentId))]public Tree Parent { get; set; }
}var list= db.Queryable<Tree>().Includes(it => it.Parent) .ToList();//DTO和List不能是同一个类不然这种映射会失效var dtolist= list.Adapt<List<TreeDTO>>();//DTO中的ParentName就有值了
2. 手动转DTO 升级: 5.1.4.71
老版本注意:是 Select 中用导航对象
//简单的用法 5.1.4.71
var list = db.Queryable<Student_004>().Includes(x => x.books).Select(x => new Student_004DTO{books = x.books }, true)//true是自动映射其他属性,匿名对象需要手动.ToList();//Mapster转换 5.1.4.71
var list = db.Queryable<Student_004>().Includes(x => x.books).Select(x => new Student_004DTO{name=x.Name,books = x.books.Adapt<List<BooksDTO>>() //导航对象用 Mapster转换 (NUGET安装)}).ToList(); //DTO中用方法 5.1.4.71
var list = db.Queryable<Student_004>().Includes(x => x.books).Select(x => new Student_004DTO{name=x.Name, //导航对象books可以是C#任何方法结尾bookIds=x.books.Select(it=>it.id).ToList(), booksDto=x.books.Select(it=>new BookDTO(){ id=it.Id,Name=it.Name }).ToList()}).ToList(); //联表查询用DTO写法 5.1.4.71
var list5= db.Queryable<Student_004>().Includes(x => x.school_001, x => x.rooms).Includes(x => x.books).LeftJoin<Order>((x, y) => x.Id==y.sid).Select((x,y) => new Student_004DTO{SchoolId = x.SchoolId,books = x.books,school_001 = x.school_001,Name=y.Name}).ToList();
2.8 导航方法
一对多和多对多
在我们一对多和多对多对象我们可以用导航方法 Any() 和导航方法 Count
//注意:不需 Includes 就可以使用
Where(it=>it.导航对象.Any())
Where(it=>it.导航对象.Any(z=>z.id==1))
Where(it=>it..导航对象.Any(List<IConditionalModel>)//5.1 //Count用法类似
一对一函数 5.1.2.9
//注意:不需 Includes 就可以使用
Where(x=>SqlFunc.Exists(x.SchoolA.Id))//查询存在一对一的主表数据
Where(x=>SqlFunc.Exists(x.SchoolA.Id,List<IConditionalModel>))//查询存在一对一的主表数据
2.9 2个同级 Root->books->[A,B]
如果 Books下面有2个导航 A 和 B
//自动写法,Books下面的A和B都会查询出来
.IncludesAllSecondLayer(x=>x.Books) //自动只能有这么多层次,更深层级需要手动写法//手动写法
.Includes(x => x.Books,x=>x.A)
.Includes(x => x.Books,x=>x.B)
3、支持联表的导航
3.1.1简单联表导航
//联表查询用DTO写法 5.1.4.71
var list5= db.Queryable<Student_004>().Includes(x => x.school_001, x => x.rooms).Includes(x => x.books).LeftJoin<Order>((x, y) => x.Id==y.sid).Select((x,y) => new Student_004DTO{SchoolId = x.SchoolId,books = x.books,school_001 = x.school_001,Name=y.Name}).ToList();
手动映射适合没有主键或者复杂的一些操作,该功能和 Includes 文档 2.4比较接近
4、特殊层级处理
4.1 创建数据
创建类
public class StudentA
{[SugarColumn(IsPrimaryKey = true)]public int StudentId { get; set; }public string Name { get; set; }public int SchoolId { get; set; }[SugarColumn(IsIgnore = true)]public SchoolA SchoolA { get; set; }
}public class SchoolA
{[SugarColumn(IsPrimaryKey = true)]public int SchoolId { get; set; }public string SchoolName { get; set; }[SugarColumn(IsIgnore = true)]public List<RoomA> RoomList { get; set; }[SugarColumn(IsIgnore = true)]public List<TeacherA> TeacherList { get; set; }
}
public class TeacherA
{[SugarColumn(IsPrimaryKey = true)]public int Id { get; set; }public int SchoolId { get; set; }public string Name { get; set; }
}
public class RoomA
{[SugarColumn(IsPrimaryKey = true)]public int RoomId { get; set; }public string RoomName { get; set; }public int SchoolId { get; set; }
}
创建测试数据
db.CodeFirst.InitTables<StudentA, RoomA, SchoolA,TeacherA>();
db.DbMaintenance.TruncateTable<StudentA>();
db.DbMaintenance.TruncateTable<RoomA>();
db.DbMaintenance.TruncateTable<SchoolA>();
db.DbMaintenance.TruncateTable<TeacherA>();
db.Insertable(new RoomA() { RoomId = 1, RoomName = "北大001室", SchoolId = 1 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 2, RoomName = "北大002室", SchoolId = 1 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 3, RoomName = "北大003室", SchoolId = 1 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 4, RoomName = "清华001厅", SchoolId = 2 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 5, RoomName = "清华002厅", SchoolId = 2 }).ExecuteCommand();
db.Insertable(new RoomA() { RoomId = 6, RoomName = "清华003厅", SchoolId = 2 }).ExecuteCommand();db.Insertable(new SchoolA() { SchoolId = 1, SchoolName = "北大" }).ExecuteCommand();
db.Insertable(new SchoolA() { SchoolId = 2, SchoolName = "清华" }).ExecuteCommand();db.Insertable(new StudentA() { StudentId = 1, SchoolId = 1, Name = "北大jack" }).ExecuteCommand();
db.Insertable(new StudentA() { StudentId = 2, SchoolId = 1, Name = "北大tom" }).ExecuteCommand();
db.Insertable(new StudentA() { StudentId = 3, SchoolId = 2, Name = "清华jack" }).ExecuteCommand();
db.Insertable(new StudentA() { StudentId = 4, SchoolId = 2, Name = "清华tom" }).ExecuteCommand();db.Insertable(new TeacherA() { SchoolId=1, Id=1, Name="北大老师01" }).ExecuteCommand();
db.Insertable(new TeacherA() { SchoolId = 1, Id =2, Name = "北大老师02" }).ExecuteCommand();db.Insertable(new TeacherA() { SchoolId = 2, Id = 3, Name = "清华老师01" }).ExecuteCommand();
db.Insertable(new TeacherA() { SchoolId = 2, Id = 4, Name = "清华老师02" }).ExecuteCommand();
4.2 手动实现二层
注意:普通导航看标题2 , ThenMapper 是用来处理 普通导航不能实现的功能
结构: Student->SchoolA
var list = db.Queryable<StudentA>().ToList();//这儿也可以联表查询
db.ThenMapper(list, stu =>
{//如果加Where不能带有stu参数,stu参数写到 SetContext//可以用Where写SetContext但是不能带有stu对象stu.SchoolA=db.Queryable<SchoolA>().SetContext(scl=>scl.SchoolId,()=>stu.SchoolId,stu).FirstOrDefault();//可以联查询的//stu.xxxx=db.Queryable<SchoolA>().LeftJoin<XXX>().Select(xxxx).SetContext(....).ToList();
});
// SetContext不会生成循环操作,高性能 和直接Where性能是不一样的
注意:1、如果没有 SetContext 那么这个查询将会循环
2、 db.ConextId 外面和里面需要是同一个
4.3 联表导航多层级
注意:普通导航看标题2, ThenMapper 是用来处理 普通导航不能实现的功能
了解原理后我们用 ThenMapper 想映射哪层就映射哪层
var treeRoot=db.Queryable<Tree>().Where(it => it.Id == 1).ToList();
//第一层
db.ThenMapper(treeRoot, item =>
{item.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => item.Id, item).ToList();
});
//第二层
db.ThenMapper(treeRoot.SelectMany(it=>it.Child), it =>
{it.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => it.Id, it).ToList();
});
//第三层
db.ThenMapper(treeRoot.SelectMany(it => it.Child).SelectMany(it=>it.Child), it =>
{it.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => it.Id, it).ToList();
});
//这儿只是用树型结构来证明可以实现无限级别导航查询 ,实际开发中树型结构用ToTree实现
public class Tree
{
[SqlSugar.SugarColumn(IsPrimaryKey =true)]
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
[SqlSugar.SugarColumn(IsIgnore = true)]
public Tree Parent { get; set; }
[SqlSugar.SugarColumn(IsIgnore = true)]
public List<Tree> Child { get; set; }
}
// SetContext不会生成循环操作,高性能 和直接Where性能是不一样的
新功能 : 请升级到5.0.6.7 预览版本 及以上
5、树型查询
后续专门章节介绍
6、不加特性使用导航
通过实体 AOP 方法实现,具体用法看实体配置
EntityService= (type, columnInfo) =>
{p.IfTable<Order>().OneToOne(it => it.Item, nameof(Order.ItemId));
}
7、自动Include 5.1.4.63
第二层的所有导航自动 Include (不支持第三层和第四层)
var list3 = db.Queryable<UnitaStudentA>().IncludesAllFirstLayer().ToList();//有重载可以排除不想要的//排除说明://IncludesAllFirstLayer(nameof(UnitaStudentA.ProjectPhases)) //这样就是排除ProjectPhases的导航属性//可以排除多个//IncludesAllFirstLayer("a","b") //自动导航如果有重复的情况: 谁在前面执行哪个
var list3 = db.Queryable<UnitaStudentA>().Includes(it=>it.Order.Where(s=>s.id==1).ToList()).IncludesAllFirstLayer().ToList();//自动导航和Order重复//根据名字导航
db.Queryable<Order>()
//等同于Includes(it=>it.ProjectPhases)
.IncludesByNameString(nameof(Order.ProjectPhases)).ToList()
可以看下图 自动导航替换了下面注释代码
注意:
第一层it下面的通过 IncludesAllFirstLayer 全自动
第二层 (it.ProjectTransferDocs) 通过 IncludesAllSecondLayer 半自动。三层四级需要全部手动
9、兼容EF CORE 非List<T>的导航
vra list=db.Queryable<Order>().Includes(it=>it.导航对象.ToList())//通过.ToList()转成SqlSugar导航类型就行.ToList();
10、泛型导航
通过鉴别器实现
var dis=db.Queryable<UnitTestDis<Cat>>().Includes(x => x.Animals).ToList();//T是Cat那么就能导航Catvar dis2 = db.Queryable<UnitTestDis<Dog>>().Includes(x => x.Animals).ToList();//T是Dog那么就能导航Dog
.NET开源 ORM 框架 SqlSugar 系列
- 【开篇】.NET开源 ORM 框架 SqlSugar 系列
- 【入门必看】.NET开源 ORM 框架 SqlSugar 系列
- 【实体配置】.NET开源 ORM 框架 SqlSugar 系列
- 【Db First】.NET开源 ORM 框架 SqlSugar 系列
- 【Code First】.NET开源 ORM 框架 SqlSugar 系列
- 【数据事务】.NET开源 ORM 框架 SqlSugar 系列
- 【连接池】.NET开源 ORM 框架 SqlSugar 系列
- 【查询目录】.NET开源 ORM 框架 SqlSugar 系列
- 【查询基础】.NET开源 ORM 框架 SqlSugar 系列
- 【排序用法】.NET开源 ORM 框架 SqlSugar 系列
- 【分组去重】.NET开源 ORM 框架 SqlSugar 系列
- 【联表查询】.NET开源 ORM 框架 SqlSugar 系列
- 【导航查询】.NET开源 ORM 框架 SqlSugar 系列
- 【子查询】.NET开源 ORM 框架 SqlSugar 系列
- 【嵌套查询】.NET开源 ORM 框架 SqlSugar 系列
相关文章:
【导航查询】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
k8s的数据库etcd报 etcdserver: mvcc: database space exceeded的处理办法
一.问题现象 公司的k8s集群的etcd配置是默认配置,其磁盘配置为2GB的配额,目前出现了数据写入失败的情况,报错Error: etcdserver: mvcc: database space exceeded。 二.处理思路 当etcd的磁盘使用达到2G后,可能会触发维护模式&am…...
【系统架构设计师】高分论文:论信息系统的安全与保密设计
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 摘要正文摘要 本人所在工作单位承担了我市城乡智慧建设工程综合管理平台项目的开发工作。我有幸参与了本项目,并担任架构师一职,全面负责项目的需求分析和系统设计等工作。城乡智慧建设工程综合管理平台项目包括…...
二分查找!
问题描述 小明在图书馆借阅书籍,图书馆的书籍在系统中按序号顺次排列,小明在借阅后,需在系统中从“在馆书籍列表”中将该书删除。请帮助小明编写一个函数,在现有列表{1, 3, 5, 6, 7, 10, 12, 14, 26, 32, 35, 39, 42, 45, 54, 56…...
学习方法的进一步迭代————4
今天又在怀疑第二大脑的可靠程度 为什么呢? 还是因为自己没记住东西,感觉没学到东西。 其实自己知道大脑本就不应该用来存放知识而是用来思考知识,但是自己还是陷在里面了,我觉得其本质不是因为认知还不够,也不是因为还有点不适…...
java将word docx pdf转换为图片(不需要额外下载压缩包,直接导入maven坐标)
(本代码实现的是将第1页转为图片,主要用于制作文件缩略图) pdf转图片容易 docx转图片麻烦,看其他博客可以直接导入maven坐标,但我知道那是需要付费且有时限的包 本着简单实用的心,我找到法子了 pdf转图片:有库直接转…...
Oracle 12c Data Guard 环境中的 GAP 修复方法
概述 上文中提到Oracle 12c 引入了多项新技术来简化 Data Guard 环境中的 GAP 修复过程,如(RECOVER … FROM SERVICE)。这些新特性不仅减少了操作步骤,还提高了效率和准确性。本文档将详细说明如何利用这些新特性进行 GAP 修复。…...
C语言:指针与数组
一、. 数组名的理解 int arr[5] { 0,1,2,3,4 }; int* p &arr[0]; 在之前我们知道要取一个数组的首元素地址就可以使用&arr[0],但其实数组名本身就是地址,而且是数组首元素的地址。在下图中我们就通过测试看出,结果确实如此。 可是…...
【Linux】理解文件系统
目录 理解磁盘物理结构存储结构 磁盘的逻辑结构逻辑抽象CHS && LBA地址的转化 文件系统块概念分区概念inode Ext2文件系统宏观认识Boot BlockBlock Group超级块(Super Block)块组描述符表(Group Descriptor Table)块位图&…...
Python爬虫——城市数据分析与市场潜能计算(Pandas库)
使用Python进行城市市场潜能分析 简介 本教程将指导您如何使用Python和Pandas库来处理城市数据,包括GDP、面积和城市间距离。我们将计算每个城市的市场潜能,这有助于了解各城市的经济影响力。 步骤 1: 准备环境 确保您的环境中安装了Python和以下库&…...
面向对象(二)——类和对象(上)
1 类的定义 做了关于对象的很多介绍,终于进入代码编写阶段。 本节中重点介绍类和对象的基本定义,属性和方法的基本使用方式。 【示例】类的定义方式 // 每一个源文件必须有且只有一个public class,并且类名和文件名保持一致! …...
嵌入式开发之ARM(一)
目录 1、认识RAM 1.2、ARM全球分布 1.3、ARM产品线 1.4、授权的厂商 1.5、ARM体系架构 1.6、ARM系统硬件组成和运行原理 2、搭建开发环境 3、ARM的工作模式及寄存器 3.1、ARM工作模式 3.2、ARM工作模式及寄存器框图 3.2.1、CPSR寄存器 1、认识RAM 成立于1990年11月,前…...
Ai编程cursor + sealos + devBox实现登录以及用户管理增删改查(十三)
一、什么是 Sealos? Sealos 是一款以 Kubernetes 为内核的云操作系统发行版。它以云原生的方式,抛弃了传统的云计算架构,转向以 Kubernetes 为云内核的新架构,使企业能够像使用个人电脑一样简单地使用云。 二、适用场景 业务运…...
手机镜头组如此突出,考虑恢复以前设计
现在手头看重照相。结果导致的问题就是,在背部要突出很高,以容纳镜头组件。这种设计真的好吗?并不见得。真实照片: VIVO X200系列镜头组照片-CSDN博客 考虑到现在镜头的情形,我建议恢复以前的设计,就是把镜…...
debian ubuntu armbian部署asp.net core 项目 开机自启动
我本地的环境是 rk3399机器,安装armbian系统。 1.安装.net core 组件 sudo apt-get update && \sudo apt-get install -y dotnet-sdk-8.0或者安装运行库,但无法生成编译项目 sudo apt-get update && \sudo apt-get install -y aspnet…...
Linux lsmod命令用于显示已经加载到内核中的模块的状态信息
1、lsmod命令 Linux lsmod命令用于显示已经加载到内核中的模块的状态信息。执行lsmod命令后会列出所有已载入系统的模块。Linux操作系统的核心具有模块化的特性,应此在编译核心时,务须把全部的功能都放入核心。您可以将这些功能编译成一个个单独的模块&…...
新增工作台模块,任务中心支持一键重跑,MeterSphere开源持续测试工具v3.5版本发布
2024年11月28日,MeterSphere开源持续测试工具正式发布v3.5版本。 在这一版本中,MeterSphere新增工作台模块,工作台可以统一汇总系统数据,提升测试数据的可视化程度并增强对数据的分析能力,为管理者提供测试工作的全局…...
歇一歇,写写段子
无聊的日子都在写段子1.0 中学的时候喜欢看意林之类的杂志, 里面的作者用乱七八糟的理由跑去旅游,然后说“阻碍你脚步的永远只有逃离的勇气和对生活的热爱”, 我觉得太对了,可惜 12306 付款方式里没有勇气和热爱,不…...
【数据库系列】Spring Boot如何配置Flyway的回调函数
Flyway 提供了回调机制,使您能够在特定的数据库迁移事件发生时执行自定义逻辑。通过实现 Flyway 的回调接口,可以在迁移前后执行操作,如记录日志、执行额外的 SQL 语句等。 1. 创建自定义回调类 要配置 Flyway 的回调函数,需要创…...
Ubuntu源码安装gitlab13.7集群多前端《二》
Ubuntu源码安装gitlab13.7《一》 gitaly需要调整的服务 redis socket->ipbind ....* # 0.0.0.0pg vim /etc/postgresql/14/main/pg_hba.confhost all all ..../32 md5gitaly vim /home/git/gitaly/config.tomlbin_dir "/home/gi…...
QT5.14 QML串口助手
基于 QML的 串口调试助手 这个代码有缺失,补了部分代码 ASCII HEX 工程共享, Qt版本 5.14.1 COM_QML 通过百度网盘分享的文件:COM_QML.zip 链接:https://pan.baidu.com/s/1MH2d6gIPDSoaX-syVWZsww?pwd5tge 提取码:…...
SQL Server 实战 - 多种连接
目录 背景 一、多种连接 1. 复合连接条件 2. 跨数据库连接 3. 隐连接 4. 自连接 5. 多表外连接 6. UNION ALL 二、一个对比例子 背景 本专栏文章以 SAP 实施顾问在实施项目中需要掌握的 sql 语句为偏向进行选题: 用例:SAP B1 的数据库工具&am…...
Netty面试内容整理-Netty 工作原理
Netty 的工作原理主要基于异步、事件驱动的 I/O 模型,结合 Reactor 多线程模式和高效内存管理来实现高并发网络通信。以下是 Netty 的工作原理详细解析: Reactor 线程模型 Netty 基于 Reactor 模式 来处理并发连接和 I/O 操作,主要分为 单线程模型、多线程模型 和 主从多线程…...
数据结构基础之《(10)—快速排序》
一、快速排序基础 1、Partition过程 给定一个数组arr,和一个整数num。请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。 要求额外空间复杂度O(1),时间复杂度O(N) 2、例子 区分小于等于num的数 (<区) [5 3 7 2 3 4 1] num…...
k8s 亲和性之Affinity
文章目录 1. Node Affinity(节点亲和性)节点亲和性类型配置示例常见场景: 2. Pod Affinity 和 Pod Anti-AffinityPod Affinity 配置示例Pod Anti-Affinity 配置示例常见场景: 3. 亲和性规则概述4. 亲和性和反亲和性的细节5. 亲和性…...
OpenNMT-py入门
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、安装二、快速开始1.准备数据2.训练模型3.翻译 总结 前言 OpenNMT-py是OpenNMT的Pytorch版本,它是一个 MIT的神经机器翻译框架。它被设计用于研…...
element-ui的下拉框报错:Cannot read properties of null (reading ‘disabled‘)
在使用element下拉框时,下拉框option必须点击输入框才关闭,点击其他地方报错:Cannot read properties of null (reading disabled) 造成报错原因:项目中使用了el-dropdown组件,但是在el-dropdown里面没有定义el-dropdo…...
【微服务】SpringBoot 对接飞书多维表格事件回调监听流程详解
目录 一、前言 二、前置准备 2.1 创建一个应用 2.2 准备一张测试使用的多维表 2.3 获取对接文档 2.4 工程中添加SDK 三、对接过程 3.1 配置Encrypt Key 和 Verification Token 3.2 配置订阅方式 3.3 添加事件 3.4 申请权限 3.5 编写订阅代码 3.6 订阅文档事件 3.7…...
docker常用命令
docker 常用命令 1、查看基本信息 docker info docker run --rm hello-world docker pull nginx docker run -p 8080:80 nginx docker image ls 查看详细信息 docker inspect nginx 查看当前正运行的容器 docker ps 后台运行容器 docker run -d -p 8080:80 nginx 给容器取个名字…...
如何调用百度文心一言API实现智能问答
诸神缄默不语-个人CSDN博文目录 百度需要先认证个人信息才能使用LLM API。 文章目录 1. 获得 API Key2. 撰写代码并实现提问和回答2.1 用openai包实现调用2.2 用openai包实现流式调用2.3 用openai包实现工具调用2.4 构建智能体2.5 文生图2.6 图生图 3. 用gradio建立大模型问答…...
数据类型扮演着至关重要的角色
在Java编程语言中,数据类型扮演着至关重要的角色,它们定义了变量能够存储的数据类型以及可以对这些数据执行的操作。Java的数据类型主要可以分为两大类:基本数据类型(也称为原始数据类型)和引用数据类型。 基本数据类…...
React 路由与组件通信:如何实现路由参数、查询参数、state和上下文的使用
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
3.STM32通信接口之SPI通信---SPI实战(W25Q64存储模块介绍)《精讲》
上一节介绍了SPI的通信过程和方法,接下来就要进行STM32与外围模块通信了,这个模块是一块非易失型存储芯片,能够提供8MB的存储空间。接下来跟着Whappy脚步,进行探索新大陆吧!【免费】W25Q64(中英文数据手册)资源-CSDN文…...
yagmail邮件发送库:如何用Python实现自动化邮件营销?
🎥 作者简介: CSDN\阿里云\腾讯云\华为云开发社区优质创作者,专注分享大数据、Python、数据库、人工智能等领域的优质内容 🌸个人主页: 长风清留杨的博客 🍃形式准则: 无论成就大小,…...
vue elementui layout布局组件实现规则的弹性布局
背景:遇到在一个容器里,采用弹性盒布局的时候,如果元素个数改变,元素的排列会错乱。 解决方式 方式一:之前遇到的时候,是采用计算元素个数的方式,采用透明元素补齐的方式(比如一个有…...
Python虚拟环境管理工具:Pipenv
Python虚拟环境管理工具:Pipenv 前言1. Pipenv的功能和特点2. 安装Pipenv3. 基本使用3.1 创建项目并初始化 Pipenv3.2 使用虚拟环境3.3 安装开发依赖3.4 查看当前依赖3.5 锁定依赖3.6 升级依赖3.7 卸载依赖 4. Pipenv vs. Poetry5. 常见问题 总结 前言 Pipenv 是一个…...
Tomcat使用教程
下载地址:https://tomcat.apache.org/ 配置环境变量 变量名: CATALINA_HOME 变量值: D:\tools\apache-tomcat-9.0.97 Path: %CATALINA_HOME%\bin 启动Tomcat(打开命令提示符) startup.bat 解决乱码问题(打开conf\logging.properties) java.util.logging.Conso…...
Flink历史服务器-History Server
在以session模式提交作业后,我们可以在session集群里查看作业的详细信息,但是假如session集群重启后,则不能再查看到之前作业的信息;或者以yarn application或per-job或k8s application模式提交,都存在一个问题,就是在作业完成后(即Flink集群关闭),无法查看作业信息,…...
redis核心命令全局命令 + redis 常见的数据结构 + redis单线程模型
文章目录 一. 核心命令1. set2. get 二. 全局命令1. keys2. exists3. del4. expire5. ttl6. type 三. redis 常见的数据结构及内部编码四. redis单线程模型 一. 核心命令 1. set set key value key 和 value 都是string类型的 对于key value, 不需要加上引号, 就是表示字符串…...
Java后端请求想接收多个对象入参的数据方法
在Java后端开发中,如果我们希望接收多个对象作为HTTP请求的入参,可以使用Spring Boot框架来简化这一过程。Spring Boot提供了强大的RESTful API支持,能够方便地处理各种HTTP请求。 1.示例:使用Spring Boot接收包含多个对象的HTTP…...
傅里叶变换FT——DFT——FFT(三者之间的关系)
FT 周期函数 f(t) 的傅里叶变换实质上是将函数信号分解为不同频率、不同幅值的正、余弦信号,如下图所示。换言之,无数个不同频率,不同幅值的正、余弦信号来不断逼近周期函数 f(t) 。 分解出的这些信号的频率都是基频 ω0 的整数倍࿰…...
华为HarmonyOS 让应用快速拥有账号能力 -- 2 获取用户头像昵称
场景介绍 如应用需要完善用户头像昵称信息,可使用Account Kit提供的头像昵称授权能力,用户允许应用获取头像昵称后,可快速完成个人信息填写。以下只针对Account kit提供的头像昵称授权能力进行介绍,若要获取头像还可通过场景化控…...
git命令-基本使用
#git安装后-指定名称和邮箱: $ git config --global user.name "Your Name" $ git config --global user.email "emailexample.com" #查看远程分支: git branch -a #查看本地分支: git branch #切换分支: git checkout…...
学习笔记050——SpringBoot学习1
文章目录 Spring Boot1、Spring Boot 配置文件2、Spring Boot 整合视图层3、Spring Boot 整合持久层 Spring Boot Spring Boot 可以快速构建基于 Spring 的 Java 应用,可以快速整合各种框架,不需要开发者进行配置,Spring Boot 会实现自动装配…...
【前端开发】微信裁剪图片上传
Cropper.js: 一款基于 JavaScript 的开源图片裁剪神器,支持图片裁剪、缩放、旋转 HTML页面引用: css:<link rel"stylesheet" type"text/css" href"css/cropper.css" /> js:<sc…...
【Golang】WaitGroup 实现原理
文章目录 前言一、介绍二、实现原理三、使用方式四、总结 前言 在并发编程中,协调多个 goroutine 的执行顺序和同步是一个常见的需求。Golang 提供了 sync.WaitGroup 来简化这一过程。WaitGroup 允许主 goroutine 等待一组 goroutine 完成工作。本文将详细介绍 syn…...
从被动响应到主动帮助,ProActive Agent开启人机交互新篇章
在人工智能领域,我们正见证着一场革命性的变革。传统的AI助手,如ChatGPT,需要明确的指令才能执行任务。但现在,清华大学联合面壁智能等团队提出了一种全新的主动式Agent交互范式——ProActive Agent,它能够主动观察环境…...
框架模块说明 #05 权限管理_03
背景 权限设计可以分为两个主要方面:操作权限和数据权限。前两篇文章已经详细介绍了操作权限的设计与实现,以及如何将其与菜单关联起来的具体方法。本篇将聚焦于数据权限,为您深入讲解相关的设计与实现方式。 全局开关 Value("${syst…...
autogen-agentchat 0.4.0.dev8版本的安装
1. 安装命令 pip install autogen-agentchat0.4.0.dev8 autogen-ext[openai]0.4.0.dev82. 版本检查 import autogen_agentchat print(autogen_agentchat.__version__)0.4.0.dev8import autogen_ext print(autogen_ext.__version__)0.4.0.dev83. 第一个案例 使用 autogen-age…...
JavaScript实现tab栏切换
JavaScript实现tab栏切换 代码功能概述 这段代码实现了一个简单的选项卡(Tab)切换功能。它通过操作 HTML 元素的类名(class)来控制哪些选项卡(Tab)和对应的内容板块显示,哪些隐藏。基本思路是先…...