贪婪加载顾名思议就是把所有要加载的东西一次性读取。
本节内容为了配合【延时加载】而诞生,贪婪加载和他本该在一起介绍,开发项目的过程中应该双管齐下,才能写出高质量的程序。
Dto 映射查询
Select().Limit(10).ToList(a => new TestDto { id = a.Id, name = a.Title });
Select().Limit(10).ToList(a => new TestDto());
Select().Limit(10).ToList(a => new TestDto { });
Select().Limit(10).ToList(a => new TestDto() { });
Select().Limit(10).ToList();
这种映射支持单表/多表。
查找规则,查找属性名,会循环内部对象 _tables(join 查询后会增长),以 主表优先查,直到查到相同的字段。
如:
A, B, C 都有 id,Dto { id, a1, a2, b1, b2 },A.id 被映射。也可以指定 id = C.id 映射。
友情提醒:在 dto 可以直接映射一个导航属性
导航属性 ManyToOne/OneToOne
ManyToOne/OneToOne 导航属性通过 ToList() 加载,这个方法有一个参数:includeNestedMembers。
参数说明:
false: 返回 2级 Join 的数据;
true: 返回所有层级深度 Join 的导航数据;
如果查询中已经使用了 a.Parent.Parent 类似表达式,则可以无需 LeftJoin 等操作。
如:
Select().Where(a => a.Parent.Name == "1").ToList();
//这样写,不需要再标记 Join,解析表达式时自动处理成 LeftJoin
如果导航属性没有使用,又想加载,可使用 Include 方法。
Select().Include(a => a.Parent).ToList();
导航属性 OneToMany/ManyToMany
IncludeMany 贪婪加载集合的导航属性,其实是分两次查询,在 ToList 后进行了数据重装。
Select().IncludeMany(a => a.Songs).ToList();
//这是 ManyToMany 关系的贪婪加载
OneToMany 的使用方法相同
IncludeMany 有第二个参数,可以进行二次查询前的修饰工作。
Select().IncludeMany(a => a.Songs,
then => then.Where(song => song.User == "admin")).ToList();
然后,其实在 then 那里,还可以继续进行向下 Include/IncludeMany。只要你喜欢,向下 100 层都没问题。
变异
变异的 IncludeMany,即使选择的不是导航属性,也可以贪婪加载。
Select().IncludeMany(a => a.TestManys.Where(b => b.TagId == a.Id));
支持联合键关系指定
比如 EFCore include 吧,如何只查询每项子集合的前几条数据,它只可以加载所有导致IO性能低下(如果某些子集合,有100条,200条),FreeSql 可以解决这个问题。
Select().IncludeMany(a => a.TestManys.Take(10));
系列文章导航
(一)入门
(二)自动迁移实体
(三)实体特性
(四)实体特性 Fluent Api
(五)插入数据
(六)批量插入数据
(七)插入数据时忽略列
(八)插入数据时指定列
(九)删除数据
(十)更新数据
(十一)更新数据 Where
(十二)更新数据时指定列
(十三)更新数据时忽略列
(十四)批量更新数据
(十五)查询数据
(十六)分页查询
(十七)联表查询
(十八)导航属性
(十九)多表查询
(二十)多表查询 WhereCascade
(二十一)查询返回数据
(二十二)Dto 映射查询
(二十三)分组、聚合
(二十四)Linq To Sql 语法使用介绍
(二十五)延时加载
(二十六)贪婪加载 Include、IncludeMany、Dto、ToList
(二十七)将已写好的 SQL 语句,与实体类映射进行二次查询
(二十八)事务
(二十九)Lambda 表达式
(三十)读写分离
(三十一)分区分表
(三十二)Aop
(三十三)CodeFirst 类型映射
(三十四)CodeFirst 迁移说明
(三十五)CodeFirst 自定义特性