实体框架核心.Include()正在过滤查询

时间:2020-03-25 16:25:14

标签: c# .net entity-framework entity-framework-core

我正在使用EF Core 3.1.3,并且有以下两个查询:

var test = await _unitOfWork.Context.PersonEmail
    .OrderBy(e => e.EmailId)
    .Take(10)
    .Include(e => e.EmailRecord)
    .ToListAsync();
var test2 = await _unitOfWork.Context.PersonEmail
    .OrderBy(e => e.EmailId)
    .Take(10)
    .ToListAsync();

我希望两个查询都返回10个结果,但是test查询中的6个项目的null属性具有EmailRecord(因为EmailRecord表不包含这些特定项目的条目)。但是实际发生的是,test查询仅返回4个结果,而test2查询返回预期的10个结果。

实体声明如下:

[Table("PersonEmail")]
public class PersonEmail
{
    public Guid PersonId { get; set; }
    public Guid EmailId { get; set; }

    [ForeignKey("PersonId, EmailId")]
    public EmailRecord EmailRecord { get; set; }
}

[Table("EmailRecord")]
public class EmailRecord
{
    public Guid PersonId { get; set; }
    public Guid EmailId { get; set; }
    public DateTimeOffset LastUpdated { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<PersonEmail>().HasKey(x => new { x.PersonId, x.EmailId });
    modelBuilder.Entity<EmailRecord>().HasKey(x => new { x.PersonId, x.EmailId });
}

1 个答案:

答案 0 :(得分:1)

这是由于(不合适的)关系配置。

定义方式

[ForeignKey("PersonId, EmailId")]
PersonEmail中的

是一对一关系,其中PersonEmail依赖(由于FK),而EmailRecord校长

如果是这样,则由于强制FK约束,“由于EmailRecord表不包含那些特定项目的条目”根本不可能发生。因此,EF Core 3.0+ Include可以正确生成inner join,它不应该过滤主集合,但是实际上由于数据库中的实际数据关系而可以过滤主集合。

要解决此问题,您必须反映实际的关系,这似乎是另一回事-与主体PersonEmail和从属EmailRecord一对一。

删除上面的[ForeignKey]属性并添加以下流利的配置:

modelBuilder.Entity<PersonEmail>()
    .HasOne(x => x.EmailRecord)
    .WithOne()
    .HasForeignKey<EmailRecord>(x => new { x.PersonId, x.EmailId });

现在Include将使用left outer join,并且不会过滤PersonEmail记录。

有关更多信息,请参阅Relationships - One-to-one EF Core文档。