FreeSql.Repository (八)级联加载
欢迎来到《FreeSql.Repository 仓储模式》系列文档,本系列文档专注介绍 【仓储+工作单元】 的使用方式。完整文档请前往 wiki 中心:https://github.com/dotnetcore/FreeSql/wiki
前面说到,仓储模式推荐使用导航属性,联表查询、子表查询都已得到解决,本文继续配置导航属性之后,多表查询如何返回数据子表、主表数据。
ManyToOne
ManyToOne 联表查询返回数据上篇已经说到,这里重温一下:
var repo = fsql.GetRepository<Topic>();
var topics = repo.Select.Include(a => a.Type).ToList();
string typeName = topics[0].Type.Name;
执行的SQL:
select
topic.*, type.name
from topic
inner join type on type.id = topic.typeid
思考:ToList 默认返回 topic.* 和 type.* 不对,因为当 Topic 下面的导航属性有很多的时候,每次都返回所有导航属性?
于是:ToList 的时候只会返回 Include 过的,或者使用过的 N对1 导航属性字段。
- repo.Select.ToList(); 返回 topic.*
- repo.Select.Include(a => a.Type).ToList(); 返回 topic.* 和 type.*
- repo.Where(a => a.Type.name == "c#").ToList(); 返回 topic.* 和 type.*,此时不需要显式使用 Include(a => a.Type)
- repo.Select.ToList(a => new { Topic = a, TypeName = a.Type.name }); 返回 topic.* 和 type.name
OneToMany
提示:ManyToMany 多对多只要配置好了,用法与 OneToMany 一样
1对N,和 N对1 是反过来看
topic 相对于 type 是 N对1
type 相对于 topic 是 1对N
class Topic
{
[Column(IsIdentity = true)]
public int id { get; set; }
public int typeid { get; set; }
[Navigate(nameof(typeid))]
public Type Type { get; set; }
}
class Type
{
[Column(IsIdentity = true)]
public int id { get; set; }
public string name { get; set; }
[Navigate(nameof(Topic.typeid))]
public List<Topic> Topics { get; set; }
}
把 Type.name 为 c# java php,以及它们的 topic 查询出来:
var repo = fsql.GetRepository<Type>();
var types = repo.Select
.IncludeMany(a => a.Topics)
.Where(a => new { "c#", "java", "php" }.Contains(a.name))
.ToList();
[
{
name : "c#",
Topics: [ 文章列表 ]
}
...
]
这种方法是从 Type 方向查询的,非常符合使用方的数据格式要求。
最终是分两次 SQL 查询数据回来的,大概是:
select * from type where name in ('c#', 'java', 'php')
select * from topics where typeid in (上一条SQL返回的id)
举一反三:
IncludeMany 级联查询,在实际开发中,还可以 IncludeMany(a => a.Topics, then => then.IncludeMany(b => b.Comments))
假设,还需要把 topic 对应的 comments 也查询出来。最多会产生三条SQL查询:
select * from type where name in ('c#', 'java', 'php')
select * from topic where typeid in (上一条SQL返回的id)
select * from comment where topicid in (上一条SQL返回的id)
思考:这样级联查询其实是有缺点的,比如 c# 下面有1000篇文章,那不是都返回了?
IncludeMany(a => a.Topics.Take(10))
这样就能解决每个分类只返回 10 条数据了,这个功能 ef/efcore 目前做不到,直到 efcore 5.0 才支持,这可能是很多人忌讳 ef 导航属性的原因之一吧。几个月前我测试了 efcore 5.0 sqlite 该功能是报错的,也许只支持 sqlserver。而 FreeSql 没有数据库种类限制,还是那句话:都是亲儿子!
关于 IncludeMany 还有更多功能请到 github wiki 文档中了解。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?