EF interroge la database à chaque fois

J'ai un context de données unique (créé une fois), et je l'utilise pour get le même logging de database plusieurs fois, par exemple, j'obtiens le même logging de produit spécifiant le même ID de produit.

Chaque fois que j'appelle, disons, context.Products.Single(p => p.ProdID == 1) , le context renvoie la même instance de l'entité produit, MAIS interroge la database à chaque fois, ce qui est visible dans SQL Server Profiler.

Je vérifie qu'il renvoie la même instance en modifiant certaines propriétés entre les appels. L'appel suivant renvoie l'instance avec les propriétés modifiées.

Pourquoi interroge-t-on la database à chaque fois, et existe-t-il un moyen d'éviter cela?

Vous pouvez utiliser ObjectContext.GetObjectByKey ( DbSet<T>.Find pour DbContext ) pour interroger une entité à l'aide de sa key. Cette méthode vérifie si l'object avec la key spécifiée est déjà attaché au context. Si oui, il returnnera cet object sans interroger la database. S'il n'existe pas dans le context, il lance une requête de database.

Les requêtes LINQ interrogent généralement la database, que les objects soient déjà attachés au context ou non. EF ne peut pas savoir à l'avance si les objects sont attachés ou non car il ne connaît pas le résultat de la requête. Votre requête LINQ par key est une exception – théoriquement – car EF peut savoir si la requête est nécessaire ou non car elle peut vérifier si l'object avec cette key est déjà attaché. Mais cette exception n'est pas gérée en tant que telle – c'est pourquoi GetObjectByKey existe – et interroge la database comme toutes les autres requêtes LINQ.

Ce qui se passe avec le résultat de la requête est déterminé par MergeOption de l'object ObjectSet. La valeur par défaut est AppendOnly ce qui signifie que le résultat de la requête est rejeté si un object avec la key est déjà attaché au context. Rien n'est écrasé ou actualisé par la requête. Seulement si un object avec la key n'existe pas dans le context, un object du résultat de la requête est matérialisé et sera attaché au context. Vous pouvez modifier ce comportement par défaut en choisissant un autre MergeOption .

Il le fait parce qu'un autre user peut avoir modifié l'logging entre le premier et le deuxième appel.

Envisagez une solution de caching si datatables sont relativement statiques.