¿Por qué Entity Framework 6.x no almacena los resultados de la caché?

Tal vez estoy malinterpretando el almacenamiento en caché que hacen DbContext y DbSet , pero tenía la impresión de que habría algo de almacenamiento en caché. Estoy viendo un comportamiento que no esperaría cuando ejecuto el siguiente código:

 var ctx = CreateAContext(); var sampleEntityId = ctx.SampleEntities.Select(i => i.Id) .Single(i => i == 3); //Calls DB as expected var cachedEntityId = ctx.SampleEntities.Select(i => i.Id) .Single(i => i == 3); //Calls DB unexpectedly 

¿Que está pasando aqui? Pensé que parte de lo que obtienes de DbSet es que primero verifica el caché local para ver si ese objeto existe antes de consultar la base de datos. ¿Existe algún tipo de opción de configuración que me falta aquí?

Lo que @ emcas88 intenta decir es que EF solo revisará la caché cuando use el método DbSet en DbSet .

El uso de .Single , .First , .Where , etc. no almacenará en caché los resultados a menos que esté utilizando el almacenamiento en caché de segundo nivel.

Esto es porque la implementación de los métodos extensores usa el método Find del contexto

 contextName.YourTableName.Find() 

para verificar primero el caché. Espero eso ayude.

A veces uso mi método de extensión:

 using System.Linq; using System.Linq.Expressions; namespace System.Data.Entity { public static class DbSetExtensions { public static TEntity FirstOrDefaultCache(this DbSet queryable, Expression> condition) where TEntity : class { return queryable .Local.FirstOrDefault(condition.Compile()) // find in local cache ?? queryable.FirstOrDefault(condition); // if local cache returns null check the db } } } 

Uso:

 db.Invoices.FirstOrDefaultCache(x => x.CustomerName == "Some name"); 

También puede reemplazar FirstOrDefault con SingleOrDetfault.

Eche un vistazo a EF Docs , encontrará respuesta allí:

Tenga en cuenta que DbSet e IDbSet siempre crean consultas en la base de datos y siempre implicarán un viaje de ida y vuelta a la base de datos, incluso si las entidades devueltas ya existen en el contexto. Una consulta se ejecuta contra la base de datos cuando:

  • Se enumera mediante una instrucción foreach (C #) o For Each (Visual Basic).
  • Se enumera mediante una operación de recostackción como ToArray , ToDictionary o ToList .
  • Los operadores de LINQ como First o Any se especifican en la parte más externa de la consulta.
  • Se DbSet siguientes métodos: el método de extensión de Load en un DbSet , DbEntityEntry.Reload y Database.ExecuteSqlCommand .

EF6 no hace resultados de almacenamiento en memoria caché de ootb. Para almacenar los resultados en caché, necesita usar un caché de segundo nivel. Vea este prometedor proyecto en CodePlex:

Caché de segundo nivel para EF 6.1

Tenga en cuenta que si los datos cambian en la base de datos, no lo sabrá de inmediato. Algunas veces esto es importante dependiendo del proyecto. 😉