为什么 Entity Framework 核心一对多关系只创建左连接?。 IsRequired 不起作用

Why Entity Framework Core one to many relationship creates only left join?. IsRequired is not working

我决定为我的 Web API 使用 Entity Framework 核心。我对一对多关系有疑问。 假设我们有 PersonPersonAddress 个实体。作为一对多关系相关的实体。

public class Person
{
  public int Id { get; set;}
  public string Name { get; set;}
  
  //Navigation property
  public ICollection<PersonAddress> Addresses { get; set;}
}

public class PersonAddress
{
  public int Id { get; set;}
  public string Street { get; set;}
  public int PersonId { get; set;}
  
  //Navigation property
  public Person Person {get;set;}
}

我在 DbContext OnModelCreating 方法中配置实体如下

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<PersonAddress>()
                .HasOne(x => x.Person)
                .WithMany(x => x.PersonAddresses)
                .IsRequired(true)
                .HasForeignKey(x => x.PersonId);
}

问题是,当我尝试让 Person 包含时,PersonAddress entityframework 使用 left join 创建了查询。但是我想用 inner join 创建。 我的代码和查询是这样的:

 var result = _dbContext.Persons.
                .Include(x => x.PersonAddresses)
                .ToList();

SELECT `l`.`*
FROM `Person` AS `l`
LEFT JOIN 
`PersonAddresses` AS `l0`
 ON `l`.`Id` = `t`.`PersonId`

我试了很多办法都没有解决。有人遇到过这个问题吗?我该如何解决?

我用的是Microsoft.EntityFrameworkCore5.0.5版本

Entity Framework created query with left join.

它是关系数据库概念的基础。无法通过数据库约束来强制 Person 至少有一个 PersonAddress。 (除非您想反转一个地址的关联,但这是另一回事,有其自身的问题)。

映射 API 也没有任何正式的说明来映射 1:1..n 关系,这在保存数据时需要客户端验证。

EF 唯一能做的就是:简单地 return 你问什么。你问 _dbContext.Persons 所以你得到了它们。 Include 并不表示您只想要有地址的人。它告诉您要包​​括所有地址 (0..n) 的人。

How can I solve it?

  1. 通过添加谓词:
_dbContext.Persons.
    .Where(p => p.PersonAddresses.Any())
    .Include(x => x.PersonAddresses)
    .ToList()

通过 OUTER JOIN + WHERE 获取正确的数据,但不如内连接。

  1. 在内存中手动写入内部连接和组
    var result = (
        from p in _dbContext.Persons
        join pa in _dbContext.Addresses on p.Id equals pa.PersonId
        select new { p, pa }
    ).AsEnumerable()
    .GroupBy(r => r.p)
    .Select(r => r.Key);

这就创建了一个你想要的带有内连接的查询,当然这很麻烦。切换到内存(或客户端评估)是必要的,因为 EF 无法翻译 GroupBy.

这个问题让我创造了一个 IncludeInner 方法作为 EF feature request