Подтвердить что ты не робот

Как распространять общие имена столбцов в сопоставлении таблицы на иерархию (TPH)

Я использую первый подход Entity Framework 4 CTP5, и у меня есть сопоставление Table per Hierarchy (TPH). Некоторые из моих классов в иерархии имеют общие свойства.

public class BaseType
{
    public int Id { get; set; }
}

public class A : BaseType
{
    public string Customer { get; set; }
    public string Order { get; set; }
}

public class B : BaseType
{
    public string Customer { get; set; }
    public string Article { get; set; }
}

public class C : BaseType
{
    public string Article { get; set; }
    public string Manufacturer { get; set; }
}

Стандартное соглашение сопоставляет это со следующими столбцами:

  • Id
  • Article1
  • Статья 2
  • customer1
  • Customer2
  • Производитель
  • Заказ
  • Тип

Я хочу, чтобы EF4 делил общие свойства, в результате получилось следующее:

  • Id
  • Статья
  • Клиент
  • Производитель
  • Заказ
  • Тип

Помимо сокращенного количества столбцов, это имеет то преимущество, что можно искать записи на основе статьи, например, без необходимости знать, какие типы имеют свойство Article.

Я попытался сопоставить каждое общее свойство с тем же столбцом:

modelBuilder.Entity<B>().Property(n => n.Article).HasColumnName("Article");
modelBuilder.Entity<C>().Property(n => n.Article).HasColumnName("Article");

но это заставило следующее исключение:

Указанная схема недействительна. Ошибки: (36,6): ошибка 0019: каждое имя свойства в типе должно быть уникальным. Название свойства "Article" уже определено.

Кто-нибудь знает, как обойти это правило проверки?

4b9b3361

Ответ 1

Нет обходного пути для обхода этой проверки. В TPH столбец либо принадлежит базовому классу, который наследуется всеми дочерними элементами, либо специализирован для дочернего класса. Вы не можете проинструктировать EF сопоставить его с двумя вашими детьми, но не для другого. Попытка сделать это (например, положив [Column(Name = "Customer")] на A.Customer и B.Customer) вызывает сообщение MetadataException с этим сообщением:

Указанная схема недействительна. Ошибки: (10,6): ошибка 0019: каждое имя свойства в типе должно быть уникальным. Имя свойства "Клиент" уже определено.


Решение TPH:

Одним из решений для этого было бы продвигать свойства Customer и Article в базовый класс:

public class BaseType {
    public int Id { get; set; }
    public string Customer { get; set; }
    public string Article { get; set; }
}

public class A : BaseType {
    public string Order { get; set; }
}

public class B : BaseType { }

public class C : BaseType {
    public string Manufacturer { get; set; }
}

Что приводит к желаемой схеме:

alt text


Решение TPT (рекомендуется):

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

public class BaseType
{
    public int Id { get; set; }
}

public class A : BaseType
{
    [Column(Name = "Customer")]
    public string Customer { get; set; }
    public string Order { get; set; }
}

public class B : BaseType
{
    [Column(Name = "Customer")]
    public string Customer { get; set; }

    [Column(Name = "Article")]
    public string Article { get; set; }
}

public class C : BaseType
{
    [Column(Name="Article")]
    public string Article { get; set; }
    public string Manufacturer { get; set; }
}

public class MyContext : DbContext
{
    public DbSet<BaseType> BaseTypes { get; set; }        

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<BaseType>().ToTable("BaseType");
        modelBuilder.Entity<A>().ToTable("A");
        modelBuilder.Entity<C>().ToTable("C");
        modelBuilder.Entity<B>().ToTable("B");          
    }
}

alt text