Peut-être que je comprends mal la mise en cache que DbContext
et DbSet
fait, mais j'avais l'impression qu'il y avait une mise en cache qui continuerait. Je constate un comportement auquel je ne m'attendais pas lorsque j'exécute le code suivant:
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 se passe t-il ici? Je pensais qu'une partie de ce que vous obtenez de DbSet
est qu'il vérifierait d'abord le cache local pour voir si cet objet existe avant d'interroger la base de données. Y a-t-il juste une sorte d'option de configuration qui me manque ici?
Ce que @ emcas88 essaie de dire est que EF ne vérifiera le cache que lorsque vous utilisez le .Find
méthode sur DbSet
.
En utilisant .Single
, .First
, .Where
, etc. ne mettra pas les résultats en cache sauf si vous utilisez une mise en cache de second niveau.
En effet, la mise en œuvre des méthodes d'extenseur, utilisez la méthode Find du contexte
contextName.YourTableName.Find()
pour vérifier d'abord le cache. J'espère que ça aide.
Parfois j'utilise ma méthode d'extension:
using System.Linq;
using System.Linq.Expressions;
namespace System.Data.Entity
{
public static class DbSetExtensions
{
public static TEntity FirstOrDefaultCache<TEntity>(this DbSet<TEntity> queryable, Expression<Func<TEntity, bool>> 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
}
}
}
Usage:
db.Invoices.FirstOrDefaultCache(x => x.CustomerName == "Some name");
Vous pouvez également remplacer FirstOrDefault par SingleOrDetfault.
Jetez un œil à EF Docs , vous y trouverez une réponse:
Notez que DbSet et IDbSet créent toujours des requêtes sur la base de données et impliquent toujours un aller-retour vers la base de données même si les entités retournées existent déjà dans le contexte. Une requête est exécutée sur la base de données lorsque:
- Il est énuméré par un foreach (C #) ou For Each (Visual Basic).
- Il est énuméré par une opération de collecte telle que
ToArray
,ToDictionary
ouToList
.- Les opérateurs LINQ tels que
First
ouAny
sont spécifiés dans la partie la plus externe de la requête.- Les méthodes suivantes sont appelées: la méthode d'extension
Load
sur unDbSet
,DbEntityEntry.Reload
, etDatabase.ExecuteSqlCommand
.
EF6 ne fait pas de mise en cache des résultats ootb. Pour mettre en cache les résultats, vous devez utiliser un cache de deuxième niveau. Voir ce projet prometteur sur CodePlex:
Mise en cache de deuxième niveau pour EF 6.1
Gardez à l'esprit que si les données changent sur la base de données, vous ne le saurez pas immédiatement. Parfois, cela est important selon le projet. ;)