2013-06-11 21 views
7

La creazione di DbContext per query in Asp.net fa sì che EF legga solo i dati dalla sua cache o esegua query su DB per gli interi set ogni volta? Conosco il caching dei metadati per AppDomain, ma per quanto riguarda solo i dati?L'EF memorizza nella cache entità tra diverse istanze di DbContext?

Contesto: l'applicazione di acquisizione e visualizzazione dati con frontend API MVC4 + Web non chiamerebbe tale "volume elevato", ma molte query restituiscono gli stessi set di dati in un intervallo di tempo più breve.

+0

io non la penso così che i dati viene memorizzato nella cache in entità è sempre query DB –

risposta

13

Entity Framework non ha una cache di dati per AppDomain, solo una cache per istanza di contesto.

Se si crea un nuovo contesto per richiesta o query, si inizia con una cache vuota e EF recupererà i dati dal database.

Inoltre, il termine "cache per istanza di contesto" può essere fuorviante in quanto non significa che EF non eseguirà query sul database se le entità sono già caricate nella cache di contesto. Il modo in cui questo funziona della cache e come è possibile sfruttare (o no) è la seguente:

  • Ogni LINQ to Entities query su un DbSet<T> o in generale su un IQueryable<T> verrà eseguito una query di database, non importa se le entità esistono già nel contesto o no. Ma se un'entità con la stessa chiave di un'entità interrogata esiste già nel contesto EF getterà via il risultato di quella query e restituirà l'istanza dell'entità memorizzata nella cache al chiamante.

    Verifica se l'entità con la stessa chiave esiste dopo ha eseguito la query. (Per le query complesse - ad esempio le query che contengono un Include -. Non può fare questo controllo prima perché non può sapere quale entità e valori chiave saranno restituiti)

    Questo è il comportamento di default (MergeOption è AppendOnly). È possibile modificare questo comportamento in OverwriteChanges e in altre opzioni, credo, ma nessuno di questi eviterà che le query LINQ generino sempre query di database.

  • Per l'interrogazione di un'entità solo con la sua chiave è possibile utilizzare GetObjectByKey o Find (con DbContext) che controllerà prima se l'entità con quella chiave è già memorizzato nella cache nel contesto e poi restituire questo oggetto in cache. In caso contrario, eseguirà una query di database per caricarlo.

  • È possibile interrogare ChangeTracker di EF, è particolarmente ben supportato con DbContext in cui si ha accesso alla cache di contesto tramite la raccolta DbSet<T>.Local.

    Il problema qui è che non esiste una logica per interrogare automaticamente il database se una query su Local non restituisce un risultato. Devi scrivere questa logica manualmente. Il problema ancora più grande è che una query su Local è LINQ-to-Objects e non LINQ-to-Entities (Local non implementa IQueryable<T>, solo IEnumerable<T>), quindi è spesso necessario riscrivere le query per agire su Local - ad esempio non è possibile utilizzare Include qui, il vostro non è possibile utilizzare alcun EntityFunctions, si otterrà un comportamento diverso per quanto riguarda i confronti di stringhe maiuscole e minuscole, ecc, ecc

+0

Grazie per l'ottima spiegazione.Finora, avevo completamente perso il fatto che la versione memorizzata nella cache potesse essere utilizzata, anche se le interrogazioni sono state emesse contro il database. Ho usato SQL Server Profiler e ho visto le query che non hanno restituito nuovi dati nella mia applicazione !? Alla fine ho scoperto che il mio MembershipProvider personalizzato era persistente dal framework tra le richieste e così pure l'istanza del contesto che manteneva. Altro codice era in esecuzione in contesti e le cose si sono completamente incasinate. –

Problemi correlati