Nel post precedente riscontravo che come due richieste sulla stessa entità venisse gestita dall'Entity Framework in maniera - per me - strana, o per meglio dire, non in modo ottimizzato, perché eseguiva due query perfettamente identiche al database. Ovviamente, come mi ha fatto notare giustamente Daniele e Cristian, è un comportamento legittimo, e anzi, sarebbe stato strano se avveniva come io lo avevo immaginato.
Scopro solo ora che nativamente esiste una sorta di cache all'interno dell'Entity Framework, ma la cosa deve essere forzata dal programmatore. Riprendendo l'esempio del mio blog precedente, si deve scrivere:
using (TestModel.TestEntities context = new TestModel.TestEntities())
{
int colore = 2;
var a = new TestModel.Articles();
a.Article = "Art3 " + DateTime.Now.ToString();
var c = context.Colors.Where(w => w.Id == colore).First();
a.Colors = c;
context.AddToArticles(a);
a = new TestModel.Articles();
a.Article = "Art4 " + DateTime.Now.ToString();
//////////////////////////////////////
object obj = null;
context.TryGetObjectByKey(
new System.Data.EntityKey(
string.Format("{0}.{1}", context.DefaultContainerName, "Colors"),
"Id",
colore), out obj);
if (obj != null)
{
// E' presente tra gli oggetti
c = (TestModel.Colors)obj;
}
else
{
// Rifaccio la query (*)
c = context.Colors.Where(w => w.Id == colore).First();
}
/////////////////////////////////////
a.Colors = c;
context.AddToArticles(a);
context.SaveChanges();
}
A venirmi in aiuto ci pensa la funzione TryGetObjectByKey che permette di cercare un oggetto per la sua key all'interno del context attuale utilizzato per l'entity framework. La sintassi è un po' intricata, ma risolve un sacco di dubbi. Ora, avviando l'esempio con il profiler avviato, vedo che viene eseguita una sola query per recuperare l'entity del colore...
Ma il TryGetObjectByKey non solo è in grado di prendere il valore se è già stata trattata, ma esegue lui stesso una query nel caso il valore non fosse presente. Il codice qui sopra potrebbe essere scritto in modo più semplice:
using (TestModel.TestEntities context = new TestModel.TestEntities())
{
int colore = 2;
var a = new TestModel.Articles();
a.Article = "Art3 " + DateTime.Now.ToString();
TestModel.Colors c;
object obj = null;
context.TryGetObjectByKey(
new System.Data.EntityKey(
string.Format("{0}.{1}", context.DefaultContainerName, "Colors"),
"Id",
colore), out obj);
c = (TestModel.Colors)obj;
a.Colors = c;
context.AddToArticles(a);
a = new TestModel.Articles();
a.Article = "Art4 " + DateTime.Now.ToString();
obj = null;
context.TryGetObjectByKey(
new System.Data.EntityKey(
string.Format("{0}.{1}", context.DefaultContainerName, "Colors"),
"Id",
colore), out obj);
c = (TestModel.Colors)obj;
a.Colors = c;
context.AddToArticles(a);
context.SaveChanges();
}
(*) Il codice non viene mai eseguito.
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
- Kubernetes, gRPC e service mesh, il 28 dicembre 2020 alle 21:43
- Game of life in Angular.js, il 29 marzo 2016 alle 18:47
- ASP.NET e RabbitMQ (con un po' di Node.js), il 18 marzo 2016 alle 19:41
- Divide et impera con c# e un message broker, il 9 marzo 2016 alle 20:43
- Button con disabilitazione dello stesso dopo il click, il 5 luglio 2009 alle 15:00
- Triplet class non è un oggetto curioso, è utilissimo!!!, il 12 settembre 2008 alle 13:11