Множественное наследование с помощью Entity Framework TPC

Я попытался отобразить некоторые классы, используя Entity Framework в стиле TPC, и получил следующую ошибку:

Ошибка: тип "A" не может быть отображен как определено, потому что он отображает унаследованные свойства из типов, которые используют разделение сущностей или другую форму наследования. Либо выберите другую стратегию отображения наследования, чтобы не отображать унаследованные свойства, либо измените все типы в иерархии, чтобы отобразить унаследованные свойства и не использовать разбиение.

Эта ошибка возникает, когда я использую следующие классы:

public abstract class BaseEntityTest
public abstract class BaseEntityTest2 : BaseEntityTest
public abstract class BaseEntityTest3 : BaseEntityTest2
public class A: BaseEntityTest3 // this class is the only one with a table in the db

В методе OnModelCreating я добавил следующий код, чтобы получить отображение TPC

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

Когда я исключаю BaseEntityTest2 из структуры (чтобы A наследовал только от BaseEntityTest вместо BaseEntityTest2), ошибка исчезает. Означает ли это, что невозможно создать это отображение, или я просто что-то пропустил?

РЕДАКТИРОВАТЬ:

Свойства классов:

public abstract class BaseEntityTest
{

    [Key]
    public Guid Id { get; set; }

    public String Info { get; set; }

    [Required]
    public DateTime CreationDate { get; set; }

    [Required]
    public String CreationUser { get; set; }

    [Required]
    public DateTime ModificationDate { get; set; }

    [Required]
    public String ModificationUser { get; set; }

    [ConcurrencyCheck]
    [Required]
    public int LockVersion { get; internal set; }
}

public abstract class BaseEntityTest2 : BaseEntityTest
{
    [Required]
    public string Name { get; set; }

    public string Description { get; set; }

}

public abstract class BaseEntityTest3: BaseEntityTest2 
{

    [Required]
    public DateTime FromDate { get; set; }

    public DateTime ThruDate { get; set; }
}

public class A: BaseEntityTest3{
    public String Test { get; set; }
}

2 ответа

Решение

Ошибка возникает для EF 4.3.1 и более ранних версий, но не для EF 4.4 и EF 5.0. (EF 4.4 на самом деле EF 5.0, но с.NET 4.0 в качестве целевой платформы.)

НО: ошибка возникает, только если вы используете ваши абстрактные классы в качестве сущностей в вашей модели, это означает, что

  • у вас либо есть DbSetдля них в вашем классе контекста, как

    public DbSet<BaseEntityTestX> BaseEntityTestXs { get; set; }
    
  • или у вас есть свободное отображение для BaseEntityTestX, немного modelBuilder.Entity<BaseEntityTestX>()... материал

  • или вы используете один из BaseEntityTestX как свойство навигации в другом (конкретном) типе объекта

Вам это нужно?

Иметь DbSet<BaseEntityTestX> в вашем контексте имеет смысл только если вы действительно хотите запросить одну из абстрактных сущностей, например:

List<BaseEntityTest> list = context.BaseEntityTests
    .Where(b => b.Info == "abc").ToList();

Результатом, конечно, является список конкретных объектов, которые наследуются от BaseEntityTest, но это может быть смесь разных типов, как некоторые Aи некоторые Bs. Вам нужны такие запросы? Или вы хотите запросить только некоторые конкретные объекты:

List<A> list = context.As
    .Where(b => b.Info == "abc").ToList();

В последнем случае вам не нужен DbSet для абстрактных базовых классов, и вам не нужно отображение наследования. Вы можете просто удалить DbSet<BaseEntityTestX> из вашего контекстного класса и удалите отображение TPC, и ваша ошибка исчезнет.

Последний пункт - наличие свойства навигации к одному из абстрактных объектов в другом объекте - не имеет смысла при отображении TPC. Это просто невозможно сопоставить с реляционной базой данных, потому что с отображением TPC нет таблицы для абстрактной сущности, следовательно, нет цели, на которую отношение внешнего ключа могло бы ссылаться из таблицы конкретного класса, имеющего свойство навигации.

Ошибка также исчезнет, ​​если вы расширите сопоставление TPC для базовых классов:

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

Но это создаст таблицы для тех абстрактных сущностей, которые, кажется, не имеют смысла для меня.

В EF6.0 его случалось когда

EntityTypeConfiguration '<' YourBaseClass '>'

не детализировал ВСЕ ваш производный класс с

        this.Map<DerivedClass1>(m =>
        {
            m.MapInheritedProperties();
            m.ToTable("..");
        });

если только один класс dervied в ассемблере не настроен так, чтобы вы получили это исключение

Другие вопросы по тегам