EF Core预加载同表多Left Join 如何优化去除冗余Include
EF Core 多同表左连接查询优化方案
问题场景
将Oracle存储过程迁移至EF Core实现时,采用预加载(eager loading)模式需要多次调用.Include()关联MRC_BATCH_INFO表的不同导航属性,会生成大量冗余的MRC_BATCH_INFO实体实例,代码冗余且内存开销高。
原Oracle查询逻辑
SELECT C.COLL_ID, MI.MRC_INC_NAME, ME.MRC_EXC_NAME, SI.STR_INC_NAME, SE.STR_EXC_NAME, AI.MSTR_INC_NAME, AE.MSTR_EXC_NAME FROM MERCHANT C ,MRC_BATCH_INFO MI ,MRC_BATCH_INFO ME ,MRC_BATCH_INFO SI ,MRC_BATCH_INFO SE ,MRC_BATCH_INFO AI ,MRC_BATCH_INFO AE WHERE C.COLL_ID = PI_COLL_ID AND C.MRC_INC_LIST_ID = MI.COLL_MRC_BATCH_ID(+) AND C.MRC_EXC_LIST_ID = ME.COLL_MRC_BATCH_ID(+) AND C.STR_INC_LIST_ID = SI.COLL_MRC_BATCH_ID(+) AND C.STR_EXC_LIST_ID = SE.COLL_MRC_BATCH_ID(+) AND C.MSTR_INC_LIST_ID = AI.COLL_MRC_BATCH_ID(+) AND C.MSTR_EXC_LIST_ID = AE.COLL_MRC_BATCH_ID(+)
当前冗余实现
var result = await _mrcRepository .Include(x=>x.MrcBatchInfo_MI) .Include(x=>x.MrcBatchInfo_ME) .Include(x=>x.MrcBatchInfo_SI) .Include(x=>x.MrcBatchInfo_SE) .Include(x=>x.MrcBatchInfo_AI) .Include(x=>x.MrcBatchInfo_AE) .Where(x=>x.CollId==collId) .ToListAsync();
最优实现方案
直接使用**投影查询(Select)**替代全量实体加载+Include逻辑,不需要编写任何.Include()语句,EF Core会自动根据投影中用到的导航属性生成和原逻辑一致的左连接SQL,同时不会生成多余的跟踪实体实例。
优化后代码
var result = await _mrcRepository .Where(x => x.CollId == collId) .Select(x => new MerchantCollDto // 替换为自定义的接收DTO即可 { CollId = x.CollId, MrcIncName = x.MrcBatchInfo_MI != null ? x.MrcBatchInfo_MI.MrcIncName : null, MrcExcName = x.MrcBatchInfo_ME != null ? x.MrcBatchInfo_ME.MrcExcName : null, StrIncName = x.MrcBatchInfo_SI != null ? x.MrcBatchInfo_SI.StrIncName : null, StrExcName = x.MrcBatchInfo_SE != null ? x.MrcBatchInfo_SE.StrExcName : null, MstrIncName = x.MrcBatchInfo_AI != null ? x.MrcBatchInfo_AI.MstrIncName : null, MstrExcName = x.MrcBatchInfo_AE != null ? x.MrcBatchInfo_AE.MstrExcName : null }) .ToListAsync();
方案优势
- 代码精简:完全移除6个冗余的
.Include()调用,逻辑更清晰 - 性能更高:EF Core生成的SQL只会查询你实际需要的字段,不会加载
MRC_BATCH_INFO表的冗余列,查询执行效率和原生SQL一致 - 内存占用低:投影结果为普通DTO/匿名类型,EF Core不会跟踪生成多余的
MRC_BATCH_INFO实体实例,内存开销大幅降低 - 逻辑完全匹配:EF Core 5.0及以上版本会自动优化多同表导航属性的连接逻辑,和原Oracle的左外连接(
(+)语法)逻辑完全对齐,不会出现结果不一致问题
提示:投影时添加空值判断是为了兼容左连接关联不到数据的场景,避免运行时抛出空引用异常,和原SQL返回null的行为完全一致。
内容的提问来源于stack exchange,提问作者Utku Yıldız
相关产品推荐
相关产品推荐

