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

如何用LINQ方法语法实现4层深度Eager Loading预加载

解决Eager Loading多层关联与筛选问题

首先先修正下类定义里的小笔误(C类的集合应该命名为Ds才和其他集合命名统一):

public class A { 
    public int Id; 
    public ICollection<B> Bs; 
} 
public class B { 
    public int Id; 
    public int AId; 
    public ICollection<C> Cs; 
} 
public class C { 
    public int Id; 
    public int BId; 
    public ICollection<D> Ds; 
} 
public class D { 
    public int Id; 
    public int CId; 
    public bool Show; 
}

1. 一次性Eager Loading所有关联数据(对应你的TSQL逻辑)

要实现多层嵌套的预加载,你需要用Include + ThenInclude的链式写法,这会让EF生成和你给出的LEFT JOIN逻辑一致的SQL,并且只执行一次数据库查询。正确的LINQ方法语法如下:

var result = db.A
    .Include(a => a.Bs) // 加载A关联的所有B集合
        .ThenInclude(b => b.Cs) // 加载每个B关联的所有C集合
            .ThenInclude(c => c.Ds) // 加载每个C关联的所有D集合
    .FirstOrDefault(a => a.Id == 1);

这个查询会一次性拉取所有层级的关联数据,完全匹配你给出的TSQL查询效果,确保只触发一次数据库调用。

2. 筛选出Show == true的D数据

如果需要在数据库层面就筛选出Show=true的D(而非加载所有D后再在内存中过滤),在EF Core 5及以上版本可以直接使用带条件的Include:

var result = db.A
    .Include(a => a.Bs)
        .ThenInclude(b => b.Cs)
            .ThenInclude(c => c.Ds.Where(d => d.Show)) // 仅加载Show为true的D
    .FirstOrDefault(a => a.Id == 1);

如果是使用EF6(不支持带条件的Include),可以通过投影来实现类似效果:

var result = db.A
    .Where(a => a.Id == 1)
    .Select(a => new {
        A = a,
        Bs = a.Bs.Select(b => new {
            B = b,
            Cs = b.Cs.Select(c => new {
                C = c,
                Ds = c.Ds.Where(d => d.Show)
            })
        })
    })
    .FirstOrDefault();

之后你可以把投影结果转换回实体类,或者直接使用这个匿名类型进行后续操作。

常见问题提醒

  • 你原代码里写了a.B,但类定义里是集合Bs,要注意命名一致性,避免加载错误或空引用。
  • 多层嵌套预加载一定要用ThenInclude,而非在Include里嵌套Select,后者是早期EF的写法,现在ThenInclude的可读性和规范性更好。

内容的提问来源于stack exchange,提问作者RoLYroLLs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:05:20