为什么 Entity Framework 核心一对多关系只创建左连接?。 IsRequired 不起作用
Why Entity Framework Core one to many relationship creates only left join?. IsRequired is not working
我决定为我的 Web API 使用 Entity Framework 核心。我对一对多关系有疑问。
假设我们有 Person
和 PersonAddress
个实体。作为一对多关系相关的实体。
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?
- 通过添加谓词:
_dbContext.Persons.
.Where(p => p.PersonAddresses.Any())
.Include(x => x.PersonAddresses)
.ToList()
通过 OUTER JOIN
+ WHERE
获取正确的数据,但不如内连接。
- 在内存中手动写入内部连接和组
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。
我决定为我的 Web API 使用 Entity Framework 核心。我对一对多关系有疑问。
假设我们有 Person
和 PersonAddress
个实体。作为一对多关系相关的实体。
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?
- 通过添加谓词:
_dbContext.Persons.
.Where(p => p.PersonAddresses.Any())
.Include(x => x.PersonAddresses)
.ToList()
通过 OUTER JOIN
+ WHERE
获取正确的数据,但不如内连接。
- 在内存中手动写入内部连接和组
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。