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

重复Include同一表是否属于代码坏味道?有无更优查询方案?

重复Include同一导航属性的代码问题与优化方案

一、重复Include是否属于代码坏味道?

是的,这种写法属于代码冗余的坏味道。虽然EF Core内部会自动合并重复的Include请求,不会生成重复的SQL JOIN,不会影响查询性能,但重复写Include(n => n.Items)和ThenInclude(n => n.ShoesList)完全没必要,会让代码显得臃肿,降低可读性和维护性——后续修改关联属性时,可能需要修改多处重复代码,增加出错概率。

二、更优的实现方法

你可以将同一上层导航属性的多个关联查询合并到一个Include链中,无需重复Include上层节点。针对你的场景,有两种简洁的写法:

方法1:强类型链式合并(推荐)

利用EF Core的ThenInclude支持在同一层级添加多个关联属性的特性,通过一次Include(n => n.Items)后,多次对ShoesList添加不同的ThenInclude:

public async Task<ShoppingCart> GetCartWithItems(string phoneNum)
{
    return await _context.ShoppingCarts.Where(n => n.UserPhoneNum == phoneNum)
        .Include(n => n.Items)
            .ThenInclude(n => n.ShoesList)
                .ThenInclude(n => n.ShoesColors)
                    .ThenInclude(n => n.ShoesSizes)
            .ThenInclude(n => n.ShoesList) // 复用上层的Items->ShoesList,添加第二个关联属性
                .ThenInclude(n => n.ShoesImages)
        .FirstAsync();
}

方法2:使用Include的重载(一次性指定多个导航路径)

如果你习惯更紧凑的写法,也可以使用Include的字符串重载(注意:字符串写法不支持编译时检查,属性名变更时容易出错,谨慎使用):

public async Task<ShoppingCart> GetCartWithItems(string phoneNum)
{
    return await _context.ShoppingCarts.Where(n => n.UserPhoneNum == phoneNum)
        .Include("Items.ShoesList.ShoesColors.ShoesSizes")
        .Include("Items.ShoesList.ShoesImages")
        .FirstAsync();
}

三、优化后的效果

两种优化写法最终生成的SQL和你原来的代码完全一致,但代码更简洁、结构更清晰,后续维护时只需要修改一处上层导航的关联逻辑即可,避免了冗余代码带来的潜在问题。

内容的提问来源于stack exchange,提问作者Senpie.mmd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:42:31