Code First, EF 4.1: как лучше всего сопоставить следующие классы с базой данных?

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

Я пытаюсь понять, как правильно сделать сопоставление с помощью 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

Таблица Base

Id

ФирстПроперти

Container_Id1

Второе свойство

Container_Id2

Третье свойство

Container_Id3

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

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

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

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

  3. Каков наилучший способ отобразить эти классы?

Я уже публиковал похожий вопрос но меня все еще волнует этот вопрос.

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


person Jean Louis    schedule 17.04.2011    source источник


Ответы (1)


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

... или в коде Fluent:

modelBuilder.Entity<FirstDescendant>().ToTable("FirstDescendants");
// the same with the other derived classes

Таким образом, вы получите таблицу для вашего класса Base, которая содержит только свойства этого класса (только Id в вашем примере) и отдельные таблицы FirstDescendants и так далее, которые имеют свойства производных классов. Таблицы связаны отношением внешнего ключа, и EF удается загрузить необходимые столбцы из двух таблиц, чтобы материализовать объект того типа, который вы запрашиваете.

Вы можете найти введение в несколько стратегий, как EF может отображать иерархии классов здесь:

Наследование с EF Code First

Изменить

На мой взгляд, TPT — это более чистый подход к сопоставлению производных классов с реляционными таблицами. TPH требует, чтобы в базе данных были столбцы, допускающие значение NULL, только для сопоставления, где вы, возможно, захотите иметь свойства, необходимые в вашей модели. Но, с другой стороны, TPH, вероятно, будет более производительным, поскольку запросы не должны соединяться с разными таблицами.

Возможным эмпирическим правилом для принятия решения может быть:

  • Если большинство свойств находится в базовом классе, а производные классы добавляют только несколько дополнительных свойств, вы можете использовать TPH.

  • Если базовый класс не содержит свойств или содержит только несколько свойств, а большинство свойств находятся в производных классах, используйте TPT.

Но плюсы и минусы этих подходов, а также третьего, Table-Per-Concrete-Class (TPC), намного лучше и подробно описаны в серии связанных статей выше.

person Slauma    schedule 17.04.2011