[英]Return parents with null children using C# EF Core .Include
我们的目标是查询数据库,使用 Entity Framework Core 和.Include(...)
扩展方法返回具有子级的对象集合,其中一些子级将为空。
我们有一个C#样板工程,并用C#模型位置的表位置的表项目。
每个项目都有一个或零个Location对象,对象如下所示:
public class Project
{
public string LocationId { get; set; }
public Location Location { get; set; }
}
public class Location
{
public string LocationId { get; set; }
}
数据库设置如下所示:
modelBuilder.Entity<Location>(entity =>
{
entity.HasKey(location => location.LocationId);
entity.ToTable("Locations");
});
modelBuilder.Entity<Project>(entity =>
{
entity.HasOne(project => project.Location).WithMany()
.HasForeignKey(x => x.LocationId);
entity.ToTable("Projects");
});
我们创建的查询是:
var projects = dbContext.Projects.Include(x => x.Location);
当我们期望LEFT OUTER JOIN时,EF 生成的 SQL 包含一个LEFT JOIN :
SELECT [project].[LocationId]
FROM [Projects] AS [project]
LEFT JOIN [Locations] AS [c] ON [project].[LocationId] = [c].[LocationId]
结果是只返回带有位置的项目。 我们想要所有项目及其位置。
从这个链接我了解到.Include(...)
决定执行 LEFT JOIN 或 LEFT OUTER JOIN 取决于外键的可空性:
Code First 根据外键的可空性推断关系的多样性。 如果该属性可为空,则该关系将注册为可选。
因为这不是发生的事情,所以缺少一些东西。
无论是否填充它们的位置,都需要进行哪些修改才能返回所有项目?
谢谢!
您可以在Include()
之后使用DefaultIfEmpty()
方法。
例如:
var projects = dbContext.Projects.Include(x => x.Location).DefaultIfEmpty()...;
我遇到了这种情况,除了生成的 SQL 是:
INNER JOIN [Blah.[Table] AS [x.Child] ON [x].[ChildId] = [x.Child].[Id]
这确实会导致问题,而问题的LEFT JOIN
会很好(正如其他人指出的那样)。
那么为什么会发生这种情况呢? 我的ChildId
是一个Guid
,我已经确保将其设为Guid?
因为可空性使其成为可选的。
接下来我尝试添加.IsRequired(false)
为映射ChildId
。 这给出了一个错误,告诉我实际问题是什么:我还在主键中包含了ChildId
(不必要的)。
从主键中删除它会导致查询更改为LEFT JOIN
,一切都很好。
在 T-SQL 中,左联接和左外联接是一回事。 Outer 关键字是可选的。 您提供的查询将返回所有产品,无论它们是否有位置。 测试一下看看。
有关更多详细信息,请参阅: SQL Server 中的 LEFT JOIN 与 LEFT OUTER JOIN
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.