Come condividere nomi di colonne comuni in un mapping Tabella per gerarchia (TPH)

Sto utilizzando il primo approccio al codice CTP5 di Entity Framework 4 e ho una mapping Tabella per gerarchia (TPH). Alcune delle mie classi nella gerarchia hanno proprietà in comune.

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

La convenzione predefinita esegue il mapping delle seguenti colonne:

  • Id
  • Articolo 1
  • Articolo 2
  • Customer1
  • Customer2
  • fabbricante
  • Ordine
  • genere

Voglio che EF4 condivida le proprietà comuni per finire con quanto segue:

  • Id
  • Articolo
  • Cliente
  • fabbricante
  • Ordine
  • genere

A parte il ridotto numero di colonne, questo ha il vantaggio di poter cercare i record basati sull’articolo, ad esempio, senza dover sapere quali tipi hanno esattamente una proprietà Article.

Ho provato a mappare ogni proprietà comune alla stessa colonna:

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

ma questo ha gettato la seguente eccezione:

Lo schema specificato non è valido. Errori: (36,6): errore 0019: ogni nome di proprietà in un tipo deve essere univoco. Il nome della proprietà “Articolo” era già definito.

Qualcuno sa come aggirare questa regola di convalida?

Non esiste alcuna soluzione alternativa per aggirare questa convalida. In TPH una colonna appartiene alla class base che è ereditata da tutti i child o è specializzata nella class child. Non puoi istruire EF a mapparlo su due dei tuoi figli, ma non sull’altro. Il tentativo di farlo (ad esempio inserendo [Column(Name = "Customer")] su A.Customer e B.Customer) causerà un MetadataException con questo messaggio:

Lo schema specificato non è valido. Errori: (10,6): errore 0019: ogni nome di proprietà in un tipo deve essere univoco. Il nome della proprietà “Cliente” era già definito.

Soluzione TPH:

Una soluzione a questo sarebbe promuovere le proprietà di Customer e Article nella 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; } } 

Quale risulta allo schema desiderato:

alt text

Soluzione TPT (consigliata):

Detto questo, consiglio di prendere in considerazione l’utilizzo di Table per Type (TPT) poiché è la soluzione migliore per il tuo scenario:

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

alt text

Per chiunque avesse problemi con questo problema, ora è stato risolto in EF6: Entity framework – Codeplex