You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:24:12