Code First, EF 4.1: Каков наилучший способ сопоставить следующие классы с базой данных ...? - PullRequest
2 голосов
/ 17 апреля 2011

Уважаемое сообщество профессиональных разработчиков!

Я пытаюсь понять, как правильно составить сопоставление с помощью Code First.

Предположим, что есть несколько классов. Один контейнерный класс, один базовый класс и несколько классов-потомков.

Базовый класс:

public class Base {

 public int Id { get; set; }

}

Классы потомков:

public class FirstDescendant {

 public string FirstProperty { get; set; }

}

public class SecondDescendant {

 public int SecondProperty { get; set; }

}

public class ThirdDescendant {

 public int ThirdProperty { get; set; }

}

Контейнер-класс:

public class Container {

 public int Id { get; set; }

 public ICollection<FirstDescendant> FirstDescendants { get; set; }

 public ICollection<SecondDescendant> SecondDescendants { get; set; }

 public ICollection<ThirdDescendant> ThirdDescendants { get; set; }

}

По умолчанию после создания DbContext и запуска моего кода я получаю две таблицы со следующей структурой:

Контейнер Стол

Id

База Стол

Id

FirstProperty

Container_Id1

SecondProperty

Container_Id2

ThirdProperty

Container_Id3

Таким образом, я получаю таблицу с именем Base, которая содержит три идентичных поля, которые имеют идентичную роль внешнего ключа.

Теперь вопросы:

  1. Мне не нравится такая избыточность. Как оценить ситуацию профессиональное сообщество, это нормально?

  2. Могу ли я изменить это? Могу ли я получить более четкую структуру базы данных?

  3. Как лучше всего сопоставить эти классы?

Я уже опубликовал аналогичный вопрос , но я все еще забочусь об этой проблеме.

Спасибо за ваши ответы и внимание.

1 Ответ

4 голосов
/ 17 апреля 2011

Структура таблицы в базе данных, которую вы получили по умолчанию, является нормальной и является результатом отображения 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) - намного лучше и детально объяснено в серии статей по теме выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...