2014-09-02 15 views
5

Abbiamo un enorme database con 770 tabelle e vogliamo fare un test delle prestazioni con EF 6.1x.Entity Framework 6 DBContext con solo un sottoinsieme di tutte le tabelle

Vogliamo interrogare solo 5 di quelle 770 tabelle. È possibile creare un DBContext "leggero" con solo 5-6 entità/DBSet invece di utilizzare l'intero contesto 770-tabelle?

Quando si utilizza il contesto completo, una query semplice con 4 join richiede 45 secondi. Sono 44 secondi troppo lunghi. Utilizziamo il codice prima (reverse engineering).

Il problema: Quando creiamo una versione come "luce" del contesto completo (vale a dire 5 tavoli solo), EF si lamenta che tutti gli altri soggetti che sono in qualche modo legati a questi 5 tabelle hanno chiavi mancanti. Mappiamo solo le chiavi, le proprietà, le relazioni per quei 5 tavoli, ma non il resto.

Poiché la query scritta in LINQ richiede solo 5 tabelle, EF deve semplicemente ignorare le altre tabelle 765, ma non lo farà. Perché no? LazyLoading = true/false non sembra avere alcuna influenza su questo.

Nota: Ovviamente si potrebbe creare una vista nel DB che esegue ciò che facciamo in codice con una query LINQ. La domanda è che si può fare con un DbContext "leggero" come sopra.

C'è la versione "light" del contesto:

public class ItemLookupContext : DbContext 
{ 
    static ItemLookupContext() 
    { 
     Database.SetInitializer<ItemLookupContext>(null); 
    } 

    public ItemLookupContext() 
     : base("Name=ItemLookupContext") 
    { 
     //Configuration.LazyLoadingEnabled = true; 
    } 

    public DbSet<Identity> Identities { get; set; } 
    public DbSet<Item> Items { get; set; } 
    public DbSet<Price> Prices { get; set; } 
    public DbSet<Department> Departments { get; set; } 
    public DbSet<Brand> Brands { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new IdentityMap()); 
     modelBuilder.Configurations.Add(new ItemMap()); 
     modelBuilder.Configurations.Add(new PriceMap()); 
     modelBuilder.Configurations.Add(new DepartmentMap()); 
     modelBuilder.Configurations.Add(new BrandMap()); 

     //ignore certain entitities to speed up loading? 
     //does not work 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
     modelBuilder.Ignore<...>(); 
    } 
} 
+1

È certamente possibile e effettivamente consigliato. In ambienti di database più grandi, è spesso un aumento delle prestazioni avere più contesti diversi per sottoinsiemi di tabelle. – DavidG

+0

un po 'di codice sarebbe utile per capire il tuo problema ma immagino che cerchi qualcosa come http://stackoverflow.com/questions/17246069/multiple-dbcontexts-on-one-db-with-code-first-migrations? – fuchs777

+0

è la query semplice il primo del file exe, ovvero la query che attiva la creazione del contesto? – tschmit007

risposta

2

Quando si ha una relazione molti-a-uno rapporto tra classe A e la classe B:

public class A 
{ 
    public B b {get; set;} 
} 
public class B 
{ 
    public ICollection<A> As {get; set;} 
} 

e definire in seguito DbContext , EF automaticamente include DbSet<B> a DbContext:

public class MyContext : DbContext 
{ 
    ... 
    public DbSet<A> As { get; set; } 
} 

Quindi, se si desidera che la vostra luce DbContext non include i relativi DbSet s, è sufficiente utilizzare Ignore metodo:

public class MyContext : DbContext 
{ 
    ... 
    public DbSet<A> As { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Ignore<B>(); 
    } 
} 
+0

grazie! Si può fare il contrario? Chiama Includi() quando necessario e chiedi a EF di ignorare tutti i DBSet per impostazione predefinita, invece di includerli? – John

+0

@John, se si ignora una classe non è possibile utilizzarla con 'Include()'. – Masoud

+0

Quello che intendevo è questo: se una tabella ha 45 riferimenti ad altri DBSet, devo chiamare Ignore() 45 volte, o c'è un modo più semplice per escludere un gran numero di insiemi correlati? – John

0

Sembra si è utilizzato uno strumento come Entity Framework Power Tools per generare l'entità classi e mappature. Questo avrebbe generato una classe per ogni tabella nel database, un contesto enorme, mappature per tutte queste classi e tutte le possibili associazioni. Questo è troppo.

Prima rimuovere tutte le classi e i mapping non necessari. Quindi rimuovi tutte le associazioni alle classi rimosse nelle poche classi che hai lasciato, non i campi di chiavi esterne primitive. Rimuovi anche tutti i DbSet dal contesto tranne i pochi che ti servono.

Questo modello di classe snellito sarà di per sé coerente. Non avrà associazioni a tutte le entità nel database, ma sarà possibile filtrare per valori di chiavi estranee che si riferiscono a entità esterne al contesto.

Se il codice è stato generato/creato in qualsiasi altro modo, questo è ancora il punto cruciale: utilizzare solo le proprietà di navigazione per altre classi nel modello di classe.Per altri riferimenti utilizzare le proprietà delle chiavi esterne primitive.

+0

Avevo paura che qualcuno lo suggerisse. Ho usato i power tool, ma il dbcontext che ho creato da alcune delle entità generate è solo uno dei molti dbcontexts di cui abbiamo bisogno. Da quello che hai scritto penso che non sia possibile usare le stesse classi di entità in più contesti. Ma allora dovrei creare la stessa classe di entità ancora e ancora per ogni dbcontext? Quindi Item1.cs per dbcontext A, Item2.cs per dbcontext B, ecc.? – John

+0

Sì, in fondo è vero. Ma penso che dovresti provare a creare contesti più ampi che coprano aggregati ragionevolmente distinti del tuo database e che servono diverse aree di attività. Pertanto, è possibile ridurre il numero di classi sovrapposte. [EntityFramework Reverse POCO Code First Generator] (https://efreversepoco.codeplex.com/documentation) potrebbe essere utile qui. –

+0

È possibile utilizzare le stesse classi di entità in diversi DbContexts, purché si crei una mappatura separata 'EntityTypeConfiguration <...>', che ha 'Ignora ();' per ogni proprietà di navigazione non si desidera che DbContext corrente provi mappare. – sliderhouserules

2

semplicemente creare il DbContext per le tabelle. Per evitare che Entity Framework si lamenti delle tabelle non mappate, è necessario disattivare l'inizializzazione del db nell'applicazione. Mettete questo nella vostra global.asax/Startup.cs

Database.SetInitializer<YourDbContext>(null); 

Racconta EF per fermare confrontando la struttura attuale DB contro il tuo DbContext. Significa anche che se qualcuno cambia le tue tabelle mappate EF, non hai alcuna possibilità di ricevere una notifica al riguardo.

Problemi correlati