Абстрактный класс с EF Core Migrations - PullRequest
1 голос
/ 13 июля 2020

Ранее мне удавалось использовать абстрактный базовый класс в DbSet, а затем наследовать от него несколько классов. Это означало бы, что все унаследованные классы отображались в одной и той же таблице, используя только нужные им столбцы. Более подробную информацию можно найти в этом сообщении (также заданном мной), но вкратце это выглядело примерно так:

public abstract class Base
{
    public int Id { get; set; }
    public DateTime CreatedDtm { get; set; }
}

public class A : Base 
{
    public string PhoneNo { get; set; }
}

public class B : Base
{
    public string EmailAddress { get; set; }
}

public DbSet<Base> Bases { get; set; }

Таблица, используемая для обоих этих классов, тогда будет иметь следующие столбцы:

  • Дискриминатор - добавлено EF для отслеживания того, какой это класс (A или B)
  • Id (используется обоими классами)
  • CreatedDtm (используется обоими классами)
  • PhoneNo (используется только A, поэтому всегда null для B )
  • Адрес электронной почты (напротив PhoneNo)

Работает, когда я сам создаю таблицу. Но когда я пытаюсь создать его с помощью EF Core Migrations, я получаю следующую ошибку:

Соответствующий тип среды CLR для типа сущности Base не может быть создан, и в модели нет производного типа сущности. который соответствует конкретному типу CLR.

Другие сообщения ( вроде этого ) предполагают, что то, что я пытаюсь сделать, невозможно, и что мне нужно использовать Table-per -Тип сопоставления. Но я видел, как это работает, поэтому не во всех случаях. Возможно ли (без изгиба вселенной) использовать абстрактный базовый класс и единую таблицу с EF Core Migrations?

1 Ответ

1 голос
/ 13 июля 2020

Я наткнулся на ответ в статье о Таблица на иерархию . Чтобы EF Core Migrations мог работать с абстрактными классами, необходимо вручную определить дискриминатор. Поэтому мне понадобилось следующее в OnModelCreation() в файле DbContext:

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<Base>()
        .ToTable("Base")
        .HasDiscriminator<string>("BaseType")
        .HasValue<A>("A")
        .HasValue<B>("B");
}

Конечно, вы можете настроить дискриминатор, как хотите, но он должен быть настроен явно.

...