Come condividere i nomi delle colonne comuni in una tabella per ogni gerarchia (TPH) Mappatura
-
10-10-2019 - |
Domanda
Sto utilizzando il codice Entity Framework 4 CTP5 primo approccio e ho una tabella per ogni gerarchia (TPH) mappatura. 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 di default associa questo per le seguenti colonne:
- Id
- Articolo 1
- Articolo 2
- Customer1
- Customer2
- Produttore
- Ordine
- Tipo
Voglio avere EF4 quota le proprietà comuni a finire con il seguente:
- Id
- Articolo
- Clienti
- Produttore
- Ordine
- Tipo
A parte il ridotto numero di colonne, questo ha il vantaggio di essere in grado di cercare i record in base all'articolo per esempio, senza dover conoscere quali tipi hanno esattamente una proprietà articolo.
Ho provato a mappare ogni proprietà comune alla stessa colonna:
modelBuilder.Entity<B>().Property(n => n.Article).HasColumnName("Article");
modelBuilder.Entity<C>().Property(n => n.Article).HasColumnName("Article");
, ma questo ha gettato la seguente eccezione:
schema specificato non è valido. Errori: (36,6): l'errore 0019: ogni nome di proprietà in un tipo devono essere univoci. Nome proprietà 'articolo' è già stato definito.
Qualcuno sa come aggirare questa regola di convalida?
Soluzione
Non v'è alcuna soluzione per bypassare questa convalida. In TPH una colonna è o appartiene alla classe di base, che è ereditato da tutti bambino o è specializzato per la classe figlia. Non è possibile indicare EF per mappare a due dei vostro bambino, ma non per gli altri. Il tentativo di farlo (ad esempio mettendo [Column(Name = "Customer")]
sia A.Customer e B.Customer) sarà causa un MetadataException con questo messaggio:
schema specificato non è valido. Errori: (10,6): l'errore 0019: ogni nome di proprietà in un tipo deve essere univoco. Nome proprietà 'cliente' è stato già definito.
TPH Soluzione:
Una soluzione a questo sarebbe quella di promuovere la Customer
e Article
proprietà alla classe di 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; }
}
Quali risultati allo schema desiderato:
TPT Solution (consigliato):
Detto questo, vi consiglio di considerare l'utilizzo di Tabella per ogni tipo (TPT) dal momento che è una migliore vestibilità per lo 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<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");
}
}
Altri suggerimenti
Per chi stava avendo problemi con questo problema, è stato risolto in EF6: quadro Entity - Codeplex