EF Core 关联数据加载核心是 Include,用于一次性获取主表及关联数据以避免 N+1 问题;多层用 ThenInclude 链式调用;可结合 Where、OrderBy、Take 过滤;需警惕笛卡尔积、深层嵌套和性能损耗。
EF Core 加载关联数据,核心就是 Include —— 它让你在查主表时,顺带把相关联的数据一次性拉回来,避免 N+1 查询问题。不用手动写 JOIN,也不用拆成多次查询,写法清晰、执行高效。
导航属性(比如 Order.Customer 或 Blog.Posts)默认不会自动加载数据。直接访问会报错或返回 null(除非开了延迟加载)。想安全取到关联对象,就得显式告诉 EF Core:“这个也要一起查”。
Include(o => o.Customer)
博客时想带上所有文章 → 用 Include(b => b.Posts)
Include(p => p.Author),再 ThenInclude(a => a.ContactInfo)
一层不够?比如“订单 → 订单项 → 商品”,就靠 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),互不干扰默认 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 好用,但乱用容易翻车:
Select 投影代替全实体加载,更轻量.AsNoTracking() 能明显提速基本上就这些。写对 Include 和 ThenInclude,关联查询就稳了一大半。