繁体   English   中英

使用 C# EF Core 返回具有空子级的父级。包括

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM