Наследование сущностей Entity Framework и пользовательские свойства

#entity-framework #inheritance #.net-core #dbset #custom-properties

Вопрос:

Моя Цель

  • У меня есть две таблицы TableA , и TableB в обеих есть одни и те же столбцы.
  • Для TableA я хочу EntityA с пользовательским свойством string Type => "A";
  • Для TableB я хочу EntityB , чтобы объект, который наследуется от EntityA и имеет пользовательское свойство string Type => "B";

Моя ситуация

Все модели созданы с Ef core power tools помощью , я создаю автоматически EntityA , но не EntityB , EntityB это копия/вставка из автоматически сгенерированного EntityA в OnModelCreatingPartial

 
// This partial class only adds a Property to the automatically generated EntityA
public partial class EntityA
{
    public virtual string Type => "A";
}

public class EntityB : EntityA
{
    public override string Type => "B";
}

public partial class MyContext
{
    public virtual DbSet<EntityB> EntityB { get; set; }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
    {
        // copy/paste from the automatically generated code for EntityA except the table name
        modelBuilder.Entity<EntityB>(entity =>
        {
            ...
            entity.ToTable("table_b");
            ...
        });
    }
}
 

Проблема

При вызове метода для извлечения EntityB я получаю ошибку.

 
private IQueryable<EntityA> GetEntitiesA(MyContext context, string? type = null)
{
    return type == null ?
        context.EntityA.Union(context.EntityB) : // EntityA and EntityB
        type == "A" ? context.EntityA : context.EntityB; // EntityA or EntityB
}
 

Ошибка:

ошибка: Microsoft.AspNetCore.Диагностика.ExceptionHandlerMiddleware[1] При выполнении запроса возникло необработанное исключение. Система.Исключение InvalidOperationException: ключ не может быть настроен в «EntityB», поскольку он является производным типом. Ключ должен быть настроен для корневого типа «EntityA». Если вы не собирались включать «EntityA» в модель, убедитесь, что на него не ссылается свойство набора базы данных в вашем контексте, на которое ссылается вызов конфигурации в ModelBuilder или на которое ссылается навигация по типу, включенному в модель.

Изменить: я смог исправить ошибку:

 public partial class MyContext
{
    public virtual DbSet<EntityB> EntityB { get; set; }

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
    {
        // copy/paste from the automatically generated code for EntityA except the table name
        modelBuilder.Entity<EntityB>(entity =>
        {
            ...
            // entity.HasKey(e => e.Id)  COMMENTING THIS WORKED
            //     .HasName("PRIMARY");
            entity.ToTable("table_b");
            ...
        });
    }
}
 

Yet still I’m unable to do the context.EntityA.Union(context.EntityB)

Unable to translate set operation when matching columns on both sides have different store types