2016-04-17 25 views
6

Penso che questo sia possibile in nibire, ma la mia domanda riguarda Entity Framework.Entity Framework: mappare più classi a una tabella

Nel mio modello di database, che non posso modificare, ho colonne ridondanti che vorrei memorizzare in classi diverse.

Esempio:

public class DateParams 
{ 
    public DateTime CreationDate { get; set; } 
    public DateTime ModificationDate { get; set; } 

    // some methods 
} 

public class Localization 
{ 
    public String EnglishLabel { get; set; } 
    public String FrenchLabel { get; set; } 

    // some methods 
} 

E poi io li uso in alcuni dei miei modelli:

public class Account // Localization && DateParams 
{ 
    public int ID { get; set; } 
    public String Name { get; set; } 

    public Localization Localization { get; set; } 
    public DateParams DateParams { get; set; } 
} 

public class Lead // DateParams only 
{ 
    public int ID { get; set; } 
    public String Name { get; set; } 

    public DateParams DateParams { get; set; } 
} 

Quello che vorrei ottenere è avere qualcosa di simile

public class LocalizationMap : EntityTypeConfiguration<Localization> 
{ 
    public LocalizationMap() 
    { 
     Property(e => e.EnglishLabel).HasColumnName("en"); 
     Property(e => e.FrenchLabel).HasColumnName("fr"); 
    } 
} 

public class AccountMap : EntityTypeConfiguration<Account> 
{ 
    public AccountMap() 
    {    
     HasKey(x => x.ID); 
     Property(e => e.Name).HasColumnName("Name"); 

     HasSubMapping(new LocalizationMap()); 
     HasSubMapping(new DateParamsMap()); 

     ToTable("Account"); 
    } 
} 

Potrei usare l'ereditarietà per risolvere questo problema, ma C# non consente l'ereditarietà multipla.

+1

Forse si dovrebbe dare un'occhiata a Entity Framework tipi complessi per esempio qui: http://stackoverflow.com/questions/9931341/entity-framework-reuse-complex-type – ChriPf

+0

@ChrifP, potresti postare il tuo commento come asnwser in modo che io possa accettarlo? Sono passato alla soluzione di tipo complesso. – Akli

risposta

3

È possibile ottenere questo utilizzando tipi complessi. Questi mappa per colonne della tabella nominato come complextypeName_propertyName ma questo comportamento può essere modificato sovrascrivendo OnModelCreating(DbModelBuilder modelBuilder) in DbContext come descritto nella Entity Framework - Reuse Complex Type

Per esempio:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.ComplexType<Localization>(); 

    modelBuilder.Entity<Account>().Property(x => x.Localization.EnglishLabel).HasColumnName("en"); 
    modelBuilder.Entity<Account>().Property(x => x.Localization.FrenchLabel).HasColumnName("fr"); 
    // et cetera 
} 
2

Non ho intenzione di renderti felice.

C'è una funzione EF chiamata Divisione tabella. Come suggerisce il nome, questo ci consente di mappare (dividere) una tabella di database in più classi nel modello concettuale. Nel tuo caso, le mappature per Account sarebbe simile a questa:

class AccountMap : EntityTypeConfiguration<Account> 
{ 
    public AccountMap() 
    { 
     ToTable("Account"); 
     HasKey(x => x.ID); 
     HasRequired(a => a.DateParams).WithRequiredPrincipal(); 
     HasRequired(a => a.Localization).WithRequiredPrincipal(); 
    } 
} 

class DateParamsMap : EntityTypeConfiguration<DateParams> 
{ 
    public DateParamsMap() 
    { 
     ToTable("Account"); 
    } 
} 

class LocalizationMap : EntityTypeConfiguration<Localization> 
{ 
    public LocalizationMap() 
    { 
     ToTable("Account"); 
    } 
} 

Ma questo dimostra subito il problema: il nome della tabella "Account" nelle configurazioni di tipo è codificato duro. Non è possibile riutilizzare le classi satellite DateParams e Localization per più tipi. E, prima di provare, EF non accetterà generici come DateParams<T>.

che è triste, perché tutte le altre opzioni che posso pensare sono brutti, o nella migliore delle ipotesi goffo:

  • creare sottoclassi di DateParams e Localization (e le configurazioni di accompagnamento) per qualsiasi entità che ha bisogno di loro.
  • Basta aggiungere le proprietà a tutti i tipi e lavorare il più possibile con le proiezioni (perché presumo che il punto principale di questo sforzo sia ridurre il numero di proprietà che si desidera interrogare).
  • Utilizzare un contesto che ospita i tipi principali senza queste proprietà e un secondo contesto che ospita i tipi di satellite (di nuovo, per facilitare l'interrogazione di meno proprietà facilmente). Sfortunatamente, è possibile unire solo le istanze di entrambi i contesti in memoria, ad esempio LINQ agli oggetti.
  • Creare una terza classe satellite, combinando entrambe le classi più piccole e utilizzare queste tre classi come tipi di base.
Problemi correlati