Por que o Entity Framework 6.x não armazena em cache os resultados?

Talvez eu esteja entendendo mal o cache que o DbSet e o DbSet fazem, mas fiquei com a impressão de que havia algum armazenamento em cache que ocorreria. Estou vendo um comportamento que não esperaria quando executar o seguinte 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 

Oque esta acontecendo aqui? Eu pensei que parte do que você obtém do DbSet é que ele primeiro verifica o cache local para ver se esse object existe antes de consultar o database. Existe apenas algum tipo de opção de configuração que estou perdendo aqui?

O que o @ emcas88 está tentando dizer é que o EF só verificará o cache quando você usar o método DbSet no DbSet .

O uso de .Single , .First , .Where , etc não armazenará em cache os resultados, a menos que você esteja usando o cache de segundo nível.

Isso ocorre porque a implementação dos methods extensores, use o método Find do contexto

 contextName.YourTableName.Find() 

para verificar primeiro o cache. Espero que ajude.

Às vezes eu uso o meu método de extensão:

 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"); 

Você pode replace FirstOrDefault por SingleOrDetfault também.

Dê uma olhada no EF Docs , você encontrará resposta lá:

Observe que DbSet e IDbSet sempre criam consultas no database e sempre envolverão uma ida e volta ao database, mesmo que as entidades retornadas já existam no contexto. Uma consulta é executada no database quando:

  • Ele é enumerado por uma instrução foreach (C #) ou For Each (Visual Basic).
  • Ele é enumerado por uma operação de coleção, como ToArray , ToDictionary ou ToList .
  • Operadores LINQ como First ou Any são especificados na parte mais externa da consulta.
  • Os seguintes methods são chamados: o método de extensão Load em um DbSet , DbEntityEntry.Reload e Database.ExecuteSqlCommand .

O EF6 não faz o cache de resultados. Para armazenar os resultados em cache, você precisa usar um cache de segundo nível. Veja este promissor projeto no CodePlex:

Cache de segundo nível para EF 6.1

Lembre-se de que, se os dados forem alterados no database, você não saberá imediatamente sobre isso. Às vezes isso é importante dependendo do projeto. 😉