У меня есть одна абстрактная родительская модель, поэтому ее экземпляры не могут быть созданы, и в настоящее время у меня есть один дочерний класс, наследующий от нее. Например, у меня есть что-то вроде этого:

public abstract class Parent {
     public virtual int Id { get; set; }
}

public class Child1 : Parent {
     public override int Id { get; set; }
     public string SomeAttribute1 { get; set; }
     public string SomeAttribute2 { get; set; }
}

Я использую структуру сущностей для заполнения моих моделей БД, и когда я добавляю

public virtual IDbSet<Child1> Child1 { get; set; } в моем контексте, я получаю следующую таблицу со следующими столбцами:

Родитель:

  • Мне бы
  • SomeAttribute1
  • SomeAttribute2

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

public class Child2 : Parent {
     public override int Id { get; set; }
     public string Child2Attribute1 { get; set; }
     public string Child2Attribute2 { get; set; }
}

И когда я добавляю эту дочернюю модель в контекст, мой столбец Parent превращается в это:

Родитель:

  • Мне бы
  • SomeAttribute1
  • SomeAttribute2
  • Child2Attribute1
  • Child2Attribute2
  • Дискриминатор

Я понимаю концепцию дискриминатора, однако моя проблема в том, что все объекты Child1, которые уже существуют в моей базе данных до добавления класса Child2, не будут иметь столбца дискриминатора, а затем будут пустыми ценности.

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

Или есть лучший способ упреждающей обработки / подготовки к добавлению дополнительных дочерних классов в более позднее время?

Или есть хороший способ сделать эти два дочерних класса своими собственными таблицами? Я никогда не делал много фантастических ООП с Entity Framework, поэтому я не уверен, каким будет лучший способ справиться с этой проблемой.

Спасибо за любую помощь!

ИЗМЕНИТЬ

Я рассмотрел 3 разные модели наследования: TPH, TPT и TPC. TPH не подходит для моего сценария, однако и TPT, и TPC могут работать. Как я уже упоминал в ответах, у меня работает TPT, однако TPC идеально подходит для моего варианта использования, поскольку я не обязательно хочу / должен хранить родительский класс в базе данных (но все равно хотел бы это в моем контексте). Мне удалось заставить TPC почти работать, внося следующие изменения в мой код:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Child1>().Map(m =>
    {
        m.MapInheritedProperties();
        m.ToTable("Child1");
    });

    modelBuilder.Entity<Child2>().Map(m =>
    {
        m.MapInheritedProperties();
        m.ToTable("Child2");
    });
}

И изменив мою родительскую модель на:

public abstract class Parent {
    [DatabaseGenerated(DatabaseGenerationOption.Identity)]
    public virtual int Id { get; set; }
}

Однако тогда проблема, которую я вижу, заключается в том, что идентификаторы, заполняемые дочерними элементами, не уникальны (т. Е. Как Child1, так и Child2 могут иметь Id = 1, однако это означает тогда имеется 2 объекта Parent с Id = 1, что нарушает ограничения уникального ключа.

Есть ли способ заставить автоматически сгенерированные идентификаторы быть уникальными для детей?

0
k1234 20 Июл 2017 в 19:40
1
Table-Per-Type предоставит вам 2 отдельные таблицы. Просто укажите имя таблицы для обоих классов (либо через атрибут, либо через свободный API).
 – 
Bradley Uffner
20 Июл 2017 в 20:01
но все равно понравилось бы в моем контексте - Почему? Если вы склоняетесь к TPC, я бы также серьезно подумал о том, чтобы EF игнорировал базовый класс и отображал каждый подтип независимо.
 – 
Gert Arnold
21 Июл 2017 в 01:51

1 ответ

Лучший ответ

Я нашел решение своей проблемы благодаря тому, что предложил Брэдли Уффнер:

Table-Per-Type добился цели, просто добавив в контекст только родительский класс, но затем создав отдельные таблицы для каждого дочернего класса по мере их добавления следующим образом:

public virtual IDbSet<Parent> Parents { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     modelBuilder.Entity<Child1>().ToTable("Child1");
     modelBuilder.Entity<Child2>().ToTable("Child2");
}
0
k1234 20 Июл 2017 в 20:27
1
У TPT есть свои недостатки, вы должны внимательно рассмотреть плюсы и минусы TPH / TPT / TPC, прежде чем принимать решение, какой из них больше подходит для вашего сценария.
 – 
Ivan Stoev
20 Июл 2017 в 20:30
Спасибо, что указали на это. Я изучил TPH, и это не то, что мне нужно, однако TPC кажется именно той структурой, которую я хочу, однако, когда я следую этому weblogs.asp.net / manavi /…, структура сущности фактически не заполняет идентификаторы дочерних таблиц.
 – 
k1234
20 Июл 2017 в 21:25