为什么实体框架核心一对多关系只创建左联接?IsRequired不起作用



我决定将实体框架核心用于我的Web API。我对一对多关系有意见。假设我们有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);
}

问题是,当我尝试获取包含PersonPersonAddress实体框架时,创建了带有左联接的查询。但我想创建内部联接。我的代码和查询是这样的:

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.EntityFrameworkCore 5.0.5版本

实体框架创建了带有左联接的查询

它是关系数据库概念的基础。没有办法通过数据库约束来强制要求Person至少有一个PersonAddress。(除非你想扭转一个地址的关联,但这是另一个有自己问题的故事(。

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

英孚唯一能做的就是:简单地把你的要求退回去。你问_dbContext.Persons,所以你得到了所有。Include并没有说明你只想要有地址的人。它告诉您希望包含其地址(0..n(的所有人。

如何解决它?

  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的特征要求。

最新更新