Ho fatto pace con l'Entity Framework: un minimo di cache!

di Andrea Zani, in .NET,

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.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese