2011-11-30 7 views
8

Ho notato che Entity Framework ha ancora molte funzionalità "automagicamente" nella loro ultima versione. Come sempre, questa è una spada a doppio taglio.È possibile disabilitare prima le relazioni automatiche in Entity Framework Code?

In particolare, sto utilizzando l'evento OnModelBuilder per creare il mio modello al volo usando il codice fluentAPI (http://msdn.microsoft.com/en-us/library/hh295844(v=vs.103) aspx). Ho una vasta serie di entità e non tutte sono conformi agli "standard" di Microsoft. Ad esempio, le mie colonne ID sono denominate Person_id anziché PersonId. In quanto tale, Entity non rileva sempre automaticamente la chiave primaria su una tabella o, almeno, sembra che non lo faccia.

Non mi interessa essere esplicito quando si crea il modello, ma ciò che mi disturba è che Non sono sempre sicuro quali proprietà e relazioni Entity rileverà automaticamente e quali ignoreranno o identificheranno erroneamente. Poiché la maggior parte delle mie entità ha anche una classe parziale con metodi e proprietà di supporto (cose per gestire enumerazioni, ecc.), Temo molto che un giorno Entity crei automaticamente mapping tra cose che non dovrebbero essere mappate (l'errore potrebbe essere Entity o qualche programmatore ignaro).

C'è un modo per disabilitare la funzione di collegamento automatico di Entity in modo che possa essere al 100% esplicito nel metodo OnModelBuilder? O, come minimo, come posso sapere quando ho bisogno di aggiungere dettagli di mappatura extra (come la necessità di dichiarare un campo opzionale, o quando una proprietà di navigazione specifica non verrà rilevata automaticamente)?

Grazie!

+0

se questa roba ti preoccupa, dovresti probabilmente usare gli aspetti "design first" di EF piuttosto che i nuovi "code first" roba –

+0

Ho iniziato con l'EDMX, per inciso. Stavo cercando di "aggiornare" in codice prima di pensare che potrebbe essere più facile da gestire dato che sarebbe tutto nel codice, ma potrebbe non valerne la pena e il debugging. – Brett

risposta

6

L'auto-magia è fatto da convenzioni all'interno del codice EF prima. Puoi rimuovere uno qualsiasi di questi conventions per disattivare un po 'di magia o puoi remove them all e successivamente dovrai essere esplicito al 100% nella tua fluent-API.

+0

Wow! Questo è esattamente ciò di cui avevo bisogno! – Brett

+0

Con EF6 la rimozione di tutte le convenzioni non aiuta ... vedere la mia risposta e lo snippet di codice pubblicati alla fine. – baHI

0

Basta essere espliciti sulle relazioni, sulle chiavi e sulle colonne nella configurazione delle entità e in realtà non dovrebbe essere un problema.

Personalmente, durante la codifica, è necessario attendere fino a quando non si rompe e quindi correggo la configurazione.

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    Database.SetInitializer<AccountWriteContext>(null); 

    modelBuilder.Configurations.Add(new AccountEntityTypeConfiguration()); 
    modelBuilder.Configurations.Add(new AccountOwnerEntityTypeConfiguration()); 
    modelBuilder.Configurations.Add(new CreditCardEntityTypeConfiguration()); 
    modelBuilder.Configurations.Add(new TenantEntityTypeConfiguration()); 
    //blah blah blah 
} 


class AccountOwnerEntityTypeConfiguration 
    : EntityTypeConfiguration<AccountOwner> 
{ 
    public AccountOwnerEntityTypeConfiguration() 
    { 
     this.HasKey(p => p.ID); 
     this.Property(p => p.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).IsRequired(); 

     this.HasRequired(o => o.CreditCard).WithMany().HasForeignKey(c => c.CreditCardID).WillCascadeOnDelete(true); 

     this.ToTable("AccountOwner", "AccountWrite"); 
    } 
} 
+0

Questo non ha mai funzionato come è scritto. Anche nell'esempio esatto, se dovessi entrare nell'entità AccountOwner e aggiungere una proprietà, EF aggiungerebbe automaticamente la proprietà nella prossima migrazione anche se non la aggiungo in EntityTypeConfiguration. – Suamere

+0

nel 2011 ha fatto. – William

-2

mi consiglia di utilizzare l'annotazione dei dati attributi per fare questo. Ad esempio, l'attributo [key] può essere utilizzato per definire la chiave primaria e l'attributo [table] può essere utilizzato per fornire il nome della tabella. L'attributo [required] può essere utilizzato per indicare a EF che è richiesto un campo.

A mio parere, è molto più semplice utilizzare la sintassi degli attributi piuttosto che utilizzare la sintassi fluente per aggiornare il modello ed è anche autodocumentante, poiché gli attributi vengono inseriti direttamente nel codice dell'oggetto.

Per ulteriori informazioni, vedere questo post del blog che elenca tutti gli attributi disponibili:

http://blogs.msdn.com/b/efdesign/archive/2010/03/30/data-annotations-in-the-entity-framework-and-code-first.aspx

+0

La domanda era "come disabilitare". E presumo senza dire esplicitamente quali colonne disabilitare. È irrilevante se preferisci le annotazioni o la sintassi fluente. L'obiettivo è avere una mappatura stabile, senza la necessità di dire esplicitamente di ignorare nuove proprietà ... – baHI

0

In realtà questo codice rimuove tutte le convenzioni, cancella anche il set iniziale ...

... ma ancora le colonne non mappate con EntityTypeConfiguration sono mappati ...

private void RemoveAllConventions(DbModelBuilder modelBuilder) 
     { 
      new List<string>() 
      { 
      "_configurationConventions", 
      "_conceptualModelConventions", 
      "_conceptualToStoreMappingConventions", 
      "_storeModelConventions" 
      } 
      .ForEach(field => 
      { 
       var values = 
        (IEnumerable<IConvention>)typeof(ConventionsConfiguration) 
         .GetField(field, BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic) 
         .GetValue(modelBuilder.Conventions); 

       modelBuilder.Conventions.Remove(values.ToArray()); 
      }); 

      var initialCS = typeof(ConventionsConfiguration) 
         .GetField("_initialConventionSet", BindingFlags.Instance | BindingFlags.GetField | BindingFlags.NonPublic) 
         .GetValue(modelBuilder.Conventions); 

      new List<string>() 
      { 
      "ConfigurationConventions", 
      "ConceptualModelConventions", 
      "ConceptualToStoreMappingConventions", 
      "StoreModelConventions" 
      } 
      .ForEach(field => 
      { 
       var values = 
        (IEnumerable<IConvention>) initialCS 
         .GetType() 
         .GetProperty(field, BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.Public) 
         .GetValue(initialCS); 

       modelBuilder.Conventions.Remove(values.ToArray()); 
      }); 


     } 
+1

Non è molto chiaro se il codice postato risponda alla domanda. È questo il tuo stato attuale delle cose, ma non funziona ancora? O questo risolve il problema, ma porta ad altre domande? – Tunaki

1

Ok, dal momento che la rimozione delle convenzioni non funziona, c'è un modo semplice per non mappare tutte le proprietà non configurate all'interno di EF6.x

L'elemento base consiste nell'utilizzare classi di mapping separate e, dopo aver eseguito le mappe manuali all'interno di una classe, è sufficiente chiamare un metodo, che con la riflessione forzerà a ignorare tutte le proprietà che non sono state configurate.

Ecco un collegamento al mio elenco, in cui è l'implementazione. Ho anche aggiunto un esempio come commento: https://gist.github.com/hidegh/36d92380c720804dee043fde8a863ecb

+0

Questo dovrebbe funzionare per tutte le proprietà, quindi anche per le raccolte (1: n) o altri riferimenti (n: 1) – baHI

Problemi correlati