EF Core 加载关联数据,核心就是 Include —— 它让你在查主表时,顺带把相关联的数据一次性拉回来,避免 N+1 查询问题。不用手动写 JOIN,也不用拆成多次查询,写法清晰、执行高效。
什么时候必须用 Include?
导航属性(比如
Order.Customer或
Blog.Posts)默认不会自动加载数据。直接访问会报错或返回 null(除非开了延迟加载)。想安全取到关联对象,就得显式告诉 EF Core:“这个也要一起查”。 查订单时想同时拿到客户信息 → 用
Include(o => o.Customer)查博客时想带上所有文章 → 用
Include(b => b.Posts)查文章时既要作者,又要作者的联系方式 → 先
Include(p => p.Author),再
ThenInclude(a => a.ContactInfo)
怎么加载多层关联?用 ThenInclude 链起来
一层不够?比如“订单 → 订单项 → 商品”,就靠
ThenInclude往下钻。它只能跟在
Include或另一个
ThenInclude后面,不能单独用。
.Include(o => o.OrderItems).ThenInclude(oi => oi.Product):订单 + 所有订单项 + 每个订单项对应的商品
.Include(b => b.Posts).ThenInclude(p => p.Author).ThenInclude(a => a.Profile):博客 + 文章 + 作者 + 作者资料 多个同级关系可并列写:
.Include(b => b.Author).Include(b => b.Posts),互不干扰
怎么只加载部分关联数据?加 Where 过滤
默认
Include会拉出全部关联记录。但有时你只需要“2025 年的订单项”或“已发布的文章”,这时可以在
Include内部做条件筛选:
.Include(o => o.OrderItems.Where(oi => oi.CreatedYear == 2025))
.Include(b => b.Posts.Where(p => p.IsPublished))还能配合
OrderBy或
Take,比如只取最新 3 篇文章:
.Include(b => b.Posts.OrderByDescending(p => p.PublishDate).Take(3))
性能和常见坑点提醒
Include 好用,但乱用容易翻车:
一对多关系里反复 Include 多个集合,可能触发笛卡尔积,结果行数暴增 深层嵌套(比如四级以上)会让 SQL 变复杂,影响可读性和执行效率 如果只用关联字段中的个别字段,建议用Select投影代替全实体加载,更轻量 不需要跟踪实体状态时,加上
.AsNoTracking()能明显提速
基本上就这些。写对 Include 和 ThenInclude,关联查询就稳了一大半。
