EF Core 在抽象派生 class 上包含导航 属性

EF Core Include navigation property on abstract derived class

我在尝试包含派生类型的导航 属性 时抛出以下异常:

System.InvalidOperationException: Invalid include.
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.PopulateIncludeTree(IncludeTreeNode includeTreeNode, Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.ProcessInclude(NavigationExpansionExpression source, Expression expression, Boolean thenInclude)
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   ...

使用以下简化的 class 结构:

public abstract class BaseJob
{
  public int Id { get; set; }
}
public abstract class WorkerJob : BaseJob
{
  public Person Person { get; set; }
}
public class PaintingJob : WorkerJob
{
  public string Color { get; set; }
}
public class Person {
  public int Id { get; set; }
  public string Name { get; set; }
}

当通过 DbContext 查询时 here:

// Throws InvalidOperationException
var jobs = await _context.BaseJobs
  .Include(job => (job as WorkerJob).Person) // WorkerJob is abstract
  .ToListAsync();

这必须与抽象 class 上存在的导航 属性 有关,因为按预期将查询调整为以下工作:

// Works as intended
var jobs = await _context.BaseJobs
  .Include(job => (job as PaintingJob).Person) // PaintingJob is concrete
  .ToListAsync();

但是,我有很多具体的派生 classes,我不想每次添加新的具体 class 时都必须更改查询。这可能是 EF Core 的错误,还是我做错了什么?

绝对不是错误,错误是我的。我错误地配置了如下上下文:

modelBuilder.Entity<PaintingJob>(entity =>
  {
    entity.HasBaseType<WorkerJob>();
    entity.HasOne(x => x.Person)
      .WithMany()
      .HasForeignKey(x => x.PersonId);
  });

在定义导航时将此更改为使用抽象 class 属性 解决了抛出的异常,并且 returns 结果符合预期。

modelBuilder.Entity<WorkerJob>(entity =>
  {
    entity.HasBaseType<BaseJob>();
    entity.HasOne(x => x.Person)
      .WithMany()
      .HasForeignKey(x => x.PersonId);
  });