EF Core怎么加载关联数据 EF Core Include方法使用教程

EF Core 关联数据加载核心是 Include,用于一次性获取主表及关联数据以避免 N+1 问题;多层用 ThenInclude 链式调用;可结合 Where、OrderBy、Take 过滤;需警惕笛卡尔积、深层嵌套和性能损耗。

EF Core 加载关联数据,核心就是 Include —— 它让你在查主表时,顺带把相关联的数据一次性拉回来,避免 N+1 查询问题。不用手动写 JOIN,也不用拆成多次查询,写法清晰、执行高效。

什么时候必须用 Include?

导航属性(比如 Order.CustomerBlog.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))
  • 还能配合 OrderByTake,比如只取最新 3 篇文章:.Include(b => b.Posts.OrderByDescending(p => p.PublishDate).Take(3))

性能和常见坑点提醒

Include 好用,但乱用容易翻车:

  • 一对多关系里反复 Include 多个集合,可能触发笛卡尔积,结果行数暴增
  • 深层嵌套(比如四级以上)会让 SQL 变复杂,影响可读性和执行效率
  • 如果只用关联字段中的个别字段,建议用 Select 投影代替全实体加载,更轻量
  • 不需要跟踪实体状态时,加上 .AsNoTracking() 能明显提速

基本上就这些。写对 Include 和 ThenInclude,关联查询就稳了一大半。