EF Core 5中加载关联数据避免重复Include的写法选型咨询
核心结论
三种写法最终生成的SQL完全一致,执行效率没有任何差异。
EF Core在执行查询前会统一解析所有Include加载规则,自动合并重复的导航路径前缀,不会因为你反复写根层级的Include()就生成重复的表JOIN,也不会因为用了短写法就减少查询复杂度,性能层面不需要做取舍,差异完全体现在可读性、可维护性上。
三种写法的具体差异
1. 标准Include()+ThenInclude()写法(你当前在用的写法)
- 优势:
- 是EF Core官方文档默认推荐的写法,IDE智能提示、重命名重构支持拉满:修改实体类导航属性名时,所有Lambda表达式会同步更新,不会出现漏改的问题。
- 关联层级一目了然,哪怕是4、5级的深层嵌套关联,顺着
ThenInclude()往下读就能理清从属关系,排查路径错误非常方便。 - 兼容所有EF Core版本,不存在版本适配问题。
- 劣势:
- 加载同一个一级导航下的多个平级子属性时,需要反复从根层级写回一级导航的
Include(),看起来有冗余,比如你示例里三次写Include(zoo => zoo.Animal)就是这类情况。
- 加载同一个一级导航下的多个平级子属性时,需要反复从根层级写回一级导航的
2. 字符串路径写法
- 优势:
- 语法最简短,写同根路径的多属性加载时代码量最少。
- 劣势:
- 完全没有编译时检查:字符串里的属性名打错、后续重构改了属性名没同步改字符串,编译阶段不会报任何错,只有运行到这段查询的时候才会抛异常,线上出问题的风险极高。
- 没有IDE智能提示,写长路径全靠记忆,出错概率非常高,生产环境不推荐使用。
3. 直接在Include()中写多级Lambda的写法
- 注意:这个写法仅在EF Core 5.0及以上版本支持,低版本EF Core用这个写法要么不加载关联数据,要么直接抛出运行时错误。
- 优势:
- 同样支持编译时检查和智能提示,安全性远高于字符串写法,简单的两级关联写起来比
Include()+ThenInclude()更简洁。
- 同样支持编译时检查和智能提示,安全性远高于字符串写法,简单的两级关联写起来比
- 劣势:
- 灵活性差:如果要加载同一个二级导航下的多个三级关联属性,还是得回到
ThenInclude()的分层写法,没法靠单级Lambda覆盖。 - 路径超过两级时可读性会快速下降,比如
Include(x => x.Zoo.Animal.Cow.Leg)这种长Lambda,远不如分层写ThenInclude()好梳理关系。
- 灵活性差:如果要加载同一个二级导航下的多个三级关联属性,还是得回到
实际开发选择建议
- 如果项目用的是EF Core 5.0以下版本,直接用标准
Include()+ThenInclude()写法即可,看似冗余但稳定性、可维护性最高。 - 如果用的是新版本EF Core,简单的两级关联可以用多级Lambda简化代码;3级及以上深层关联、同个父导航下加载多个平级子属性的场景,还是优先选标准写法,后续改代码的时候不容易出错。
- 除非是写动态查询、需要动态拼接导航路径的特殊场景,否则永远不要用字符串路径的写法。
内容的提问来源于stack exchange,提问作者WyattH7
相关产品推荐
相关产品推荐

