Entity Framework TPH поверх TPT

Эта проблема будет объяснена для трех классов: Учетная запись, Индивидуальная учетная запись и Доктор:

  • Первые два класса являются абстрактными
  • IndividualAccount является подклассом Account.
  • Доктор является подклассом IndividualAccount.

Первый уровень наследования (между Account и IndividualAccount) реализуется с помощью методологии Table Per Type. Второй уровень наследования (между IndividualAccount и Doctor) внедряется с помощью методологии Table per Hierarchy.

Конфигурации Fluent API следующие:

class AccountConfiguration : EntityTypeConfiguration<Account>
  public AccountConfiguration()
  {
    HasKey(x => x.Id);
    ...
  }
}

class IndividualAccountConfiguration : EntityTypeConfiguration<IndividualAccount>
{
  public IndividualAccountConfiguration()
  {
    ToTable("IndividualAccounts");
    ...
  }
}

class DoctorConfiguration : EntityTypeConfiguration<Doctor>
{
  public DoctorConfiguration()
  {
    ...
  }
}

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

Проблема возникает, когда я пытаюсь получить Доктора по его идентификатору. Будет выдано исключение, утверждающее, что многие столбцы недействительны, самый важный из них:
Недопустимое имя столбца «Дискриминатор».\r\n

К моему удивлению, если я размещу [Table("IndividualAccounts")] над определением класса IndividualAccount, проблема будет решена. Но я уже установил имя таблицы в конфигурации (Fluent API). Почему я должен использовать аннотацию в дополнение к Fluent API?

Обновление
При наличии аннотации свойства доктора помещаются в таблицу IndividualAccounts, чего мы и ожидали. Но если я удалю аннотацию, будет создана новая миграция, пытающаяся переместить эти поля в базовую таблицу Account!


person mdoust    schedule 05.09.2016    source источник


Ответы (1)


К моему удивлению, если я размещу [Table("IndividualAccounts")] над определением класса IndividualAccount, проблема будет решена. Но я уже установил имя таблицы в конфигурации (Fluent API). Почему я должен использовать аннотацию в дополнение к Fluent API?

Нет, проблема не решена, теперь проблема скрыта. Просто проверьте это с помощью SSM, таблица IndividualAccounts не содержит столбца Discriminator!

ToTable("IndividualAccounts");

генерирует исключение UnsupportedHybridInheritanceMapping, просто включите все исключения, и вы получите:

Больше информации:

Множественное наследование с Entity Framework TPC


Я изменил свои классы, чтобы теперь я мог видеть и дискриминатор.

В следующий раз, пожалуйста, опубликуйте свои классы с вопросом. Дополнительная информация: Как создать минимальный, полный и проверяемый пример

Если вы используете приведенный ниже код строки, это отключит исключение соглашения, но позже вы получите другие проблемы:

modelBuilder.Conventions.Remove<MappingInheritedPropertiesSupportConvention>();

Проблема EF пытается создать TPC, а не TPT. Я свяжусь с EF-Team и дам вам отзыв.

person Bassam Alugili    schedule 05.09.2016
comment
Спасибо за ваш ответ. Что касается таблиц, настроенных не так, как я хотел, я проверил их снова, и они действительно настроены так, как я объяснил выше, то есть таблица IndividualAccounts действительно содержит столбец Discriminator, и все приложение работает нормально вокруг него. Что касается более простой конструкции, мы рассмотрели множество альтернатив, и эта больше подходила для наших требований. - person mdoust; 05.09.2016
comment
@mdoust опубликуйте, пожалуйста, ваши классы, ваш DbContext и ваши полные DbConfigurations, чего-то не хватает. Я создал объекты точно так же, как ваше описание, но у меня отсутствует столбец «Дискриминатор»!? - person Bassam Alugili; 06.09.2016