Como compartilhar nomes de coluna comuns em um mapeamento de tabela por hierarquia (TPH)

Estou usando a primeira abordagem do código CTP5 do Entity Framework 4 e tenho um mapeamento de Tabela por Hierarquia (TPH). Algumas das minhas classs na hierarquia têm propriedades em comum.

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; } } 

A convenção padrão mapeia isso para as seguintes colunas:

  • Identidade
  • Artigo 1
  • Artigo2
  • Customer1
  • Customer2
  • Fabricante
  • Ordem
  • Tipo

Eu quero que o EF4 compartilhe as propriedades comuns para terminar com o seguinte:

  • Identidade
  • Artigo
  • Cliente
  • Fabricante
  • Ordem
  • Tipo

Além do número reduzido de colunas, isso tem a vantagem de poder pesquisar registros com base no artigo, por exemplo, sem precisar saber quais tipos têm exatamente uma propriedade de artigo.

Eu tentei mapear cada propriedade comum para a mesma coluna:

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

mas isso jogou a seguinte exceção:

Esquema especificado não é válido. Erros: (36,6): erro 0019: Cada nome de propriedade em um tipo deve ser exclusivo. O nome da propriedade ‘Article’ já estava definido.

Alguém sabe como contornar essa regra de validação?

Não há solução alternativa para ignorar essa validação. No TPH, uma coluna pertence à class base que é herdada por todas as crianças ou é especializada para a class filha. Você não pode instruir o EF para mapeá-lo para dois de seus filhos, mas não para o outro. A tentativa de fazer isso (por exemplo, colocando [Column(Name = "Customer")] no A.Customer e no B.Customer) estará causando uma MetadataException com esta mensagem:

Esquema especificado não é válido. Erros: (10,6): erro 0019: Cada nome de propriedade em um tipo deve ser exclusivo. O nome da propriedade “Cliente” já estava definido.

Solução TPH:

Uma solução para isso seria promover as propriedades Customer e Article na class base:

 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; } } 

Quais resultados resultam no esquema desejado:

texto alternativo

Solução TPT (Recomendado):

Dito isso, recomendo considerar o uso de tabela por tipo (TPT), pois é mais adequado ao seu cenário:

 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 BaseTypes { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().ToTable("BaseType"); modelBuilder.Entity().ToTable("A"); modelBuilder.Entity().ToTable("C"); modelBuilder.Entity().ToTable("B"); } } 

texto alternativo

Para qualquer um que estava tendo problemas com esse problema, ele foi corrigido no EF6: Entity framework – Codeplex