Структура таблицы в базе данных, которую вы получили по умолчанию, является нормальной и является результатом отображения Table-Per-Hierarchy (TPH) . Это стратегия по умолчанию для сопоставления иерархии классов с таблицами реляционной базы данных. В этой стратегии свойства всех производных классов объединяются в одну таблицу, а типы различаются только по столбцу дискриминатора в таблице.
Если вам нужна отдельная таблица для каждого класса в вашей иерархии, вы можете использовать стратегию Table-Per-Type (TPT) . Но это не значение по умолчанию, и вы должны указать это явно аннотациями данных ...
[Table("FirstDescendants")]
public class FirstDescendant : Base
{
public string FirstProperty { get; set; }
}
// the same with the other derived classes
... или в свободном коде:
modelBuilder.Entity<FirstDescendant>().ToTable("FirstDescendants");
// the same with the other derived classes
Таким образом, вы получите таблицу для вашего Base
класса, которая содержит только свойства этого класса (только Id
в вашем примере) и отдельные таблицы FirstDescendants
и т. Д., Которые имеют свойства производного классы. Таблицы связаны отношением внешнего ключа, и EF удается загрузить требуемые столбцы из двух таблиц для материализации объекта запрашиваемого вами типа.
Вы можете найти введение в несколько стратегий, как EF может отображать иерархии классов здесь:
Наследование с первым кодом EF
Редактировать
По моему мнению, TPT - более чистый подход для отображения производных классов в реляционные таблицы. TPH требует, чтобы в базе данных были столбцы, которые можно обнулять, только для отображения, где вы, возможно, захотите иметь свойства, требуемые в вашей модели. Но с другой стороны, TPH, вероятно, будет более производительным, потому что запросы не должны объединять разные таблицы.
Возможное эмпирическое правило для принятия решения может быть:
Если большинство свойств находится в базовом классе, а производные классы добавляют только несколько дополнительных свойств, вы можете использовать TPH.
Если базовый класс не содержит или содержит только несколько свойств, а большинство свойств находятся в производных классах, используйте TPT.
Но «за» и «против» подходов - также и третьего - Table-Per-Concrete-Class (TPC) - намного лучше и детально объяснено в серии статей по теме выше.