EF Core 5+可选多对多AsSplitQuery生成INNER JOIN丢失数据问题
运行环境
- .NET 5
- EF Core 5
- SQL Server
问题描述
需要通过Include().ThenInclude()语法对可选多对多关系生成LEFT JOIN查询,但EF Core实际生成INNER JOIN,导致不存在关联关系的记录被过滤丢失。
当前业务涉及三张表:A、B、AB,其中AB为A和B的多对多关联表;由于AB表需存储额外字段,未采用EF Core隐式多对多映射实现。
涉及表结构
表A
| ID |
|---|
| 1 |
| 2 |
| ... |
表B
| ID |
|---|
| 1 |
| 2 |
| ... |
关联表AB
| ID | AID | BID |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| ... | ... | ... |
C#实体模型定义
public class A { public Guid ID { get; set; } public ICollection<AB> ABs { get; set; } }
public class B { public Guid ID { get; set; } public ICollection<AB> ABs { get; set; } }
public class AB { public Guid ID { get; set; } public Guid AID { get; set; } public Guid BID { get; set; } public A A { get; set; } public B B { get; set; } }
初始查询实现
context.As .AsSplitQuery() .Include(f => f.ABs) .ThenInclude(f => f.B) .ToList();
当A记录存在对应AB关联数据时,查询逻辑正常,可正常获取A关联的所有B记录;但当A记录在AB表中无对应关联行(即未分配任何B关联数据)时,EF Core生成的SQL使用INNER JOIN关联,直接过滤掉了所有无对应AB记录的A行。
已尝试的排查方案
- 为导航属性添加可空标记:EF Core 5取消了显式标记关系为必填/可选的配置方式,改为通过模型中导航属性是否可为空自动推断关系类型。但
ICollection类型本身天然可为空,代码中指向的B实体类型也为引用类型可为空,即使主动为属性添加?可空标记(如public ICollection<AB>? ABs { get; set; }),生成的SQL仍未发生变化。 - 通过Fluent API显式配置多对多关系:参考公开方案在DbContext中配置多对多关系,仍未改变该行为,配置代码如下:
modelBuilder.Entity<A>() .HasMany(f => f.Bs) .WithMany(f => f.As);
待解决疑问
除手动编写JOIN语句外,是否有方案可强制EF Core将AB导航属性识别为可选关系,生成正确的LEFT JOIN?
问题排查更新
经测试,该现象为使用AsSplitQuery()方法的副作用,将查询改为AsSingleQuery()模式后可正常生成LEFT JOIN。
目前推测该问题与拆分查询模式下ThenInclude()加载非空一对多关系的生成逻辑有关,待进一步确认两点:
- 该现象是否为EF Core的已知bug
- 是否存在配置方式可告知EF Core上游关系为可选,即使下游关系为必填也可在拆分查询模式下生成正确的LEFT JOIN逻辑
内容的提问来源于stack exchange,提问作者Siegen
相关产品推荐
相关产品推荐

