Quelle différence fait .AsNoTracking ()?

228

J'ai une question concernant l' .AsNoTracking()extension, car c'est tout à fait nouveau et assez déroutant.

J'utilise un contexte par demande pour un site Web.

Beaucoup de mes entités ne changent pas, donc je n'ai pas besoin d'être suivi, mais j'ai le scénario suivant où je ne suis pas sûr de ce qui va dans la base de données, ou même si cela fait une différence dans ce cas.

Cet exemple est ce que je fais actuellement:

context.Set<User>().AsNoTracking()
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

C'est la même chose que ci-dessus mais en supprimant l' .AsNoTracking()étape 1:

context.Set<User>();
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

Les étapes 1 et 2 utilisent le même contexte mais se produisent à des moments différents. Ce que je ne peux pas déterminer, c'est s'il y a une différence. Comme l'étape 2 est une mise à jour, je suppose que les deux frapperont la base de données de toute façon.

Quelqu'un peut-il me dire quelle est la différence?

dotnetnoob
la source

Réponses:

187

La différence est que dans le premier cas, l'utilisateur récupéré n'est pas suivi par le contexte, donc lorsque vous allez enregistrer l'utilisateur dans la base de données, vous devez le joindre et définir correctement l'état de l'utilisateur afin qu'EF sache qu'il doit mettre à jour l'utilisateur existant au lieu d'en insérer un nouveau. Dans le second cas, vous n'avez pas besoin de le faire si vous chargez et enregistrez l'utilisateur avec la même instance de contexte car le mécanisme de suivi gère cela pour vous.

Ladislav Mrnka
la source
1
Pouvons-nous obtenir les mêmes avantages pour les classes anonymes dans une requête sélectionnée, telles que context.Users.Select (u => new {Name = u.Name})? Merci.
Dilhan Jayathilake
6
@DilhanJayathilake: Les classes anonymes ne représentent pas l'entité elle-même, donc elles n'ont pas de suivi.
Ladislav Mrnka
1
Comme EF6 infère parfois la clé d'entité de manière incorrecte sur une vue, AsNoTracking () ignore-t-il la clé et constitue-t-il donc une alternative à la correction manuelle de la clé (en supposant que d'autres avantages de la clé ne sont pas nécessaires).
crokusek
4
Notez également que le plus grand effet d'AsNoTracking est que le chargement paresseux ne fonctionnera pas
Douglas Gaskell
170

voir cette page Entity Framework et AsNoTracking

Ce que fait AsNoTracking

Entity Framework expose un certain nombre d'options de réglage des performances pour vous aider à optimiser les performances de vos applications. L'une de ces options de réglage est .AsNoTracking(). Cette optimisation vous permet de dire de Entity Frameworkne pas suivre les résultats d'une requête. Cela signifie qu'il Entity Frameworkn'effectue aucun traitement ou stockage supplémentaire des entités renvoyées par la requête. Cependant, cela signifie également que vous ne pouvez pas mettre à jour ces entités sans les rattacher au graphique de suivi.

il y a des gains de performances importants à réaliser en utilisant AsNoTracking

Moji
la source
11
Il semble que les gains puissent parfois être contrebalancés: stackoverflow.com/questions/9259480/…
Fabrice
3
Mon gain de performances avec une requête complexe chargeant une relation parent-enfant avec l'inclusion en une seule étape était d'environ 50%
Karl
53

Pas de suivi des requêtes LINQ to Entities

L'utilisation de AsNoTracking () est recommandée lorsque votre requête est destinée aux opérations de lecture. Dans ces scénarios, vous récupérez vos entités mais elles ne sont pas suivies par votre contexte, ce qui garantit une utilisation minimale de la mémoire et des performances optimales

Avantages

  1. Amélioration des performances par rapport aux requêtes LINQ régulières.
  2. Objets entièrement matérialisés.
  3. Le plus simple à écrire avec une syntaxe intégrée au langage de programmation.

Les inconvénients

  1. Ne convient pas aux opérations CUD.
  2. Certaines restrictions techniques, telles que: les modèles utilisant DefaultIfEmpty pour les requêtes OUTER JOIN entraînent des requêtes plus complexes que les simples instructions OUTER JOIN dans Entity SQL.
  3. Vous ne pouvez toujours pas utiliser LIKE avec la correspondance de modèle générale.

Plus d'informations disponibles ici:

Considérations de performances pour Entity Framework

Entity Framework et NoTracking

NullReference
la source
34

La désactivation du suivi entraînera également la diffusion de vos jeux de résultats en mémoire. Ceci est plus efficace lorsque vous travaillez avec de grands ensembles de données et que vous n'avez pas besoin de l'ensemble de données en une seule fois.

Références:

Ronnie Overby
la source
10

AsNoTracking () permet de contourner l'exigence de "clé unique par enregistrement" dans EF (non mentionnée explicitement par d'autres réponses).

Cela est extrêmement utile lors de la lecture d'une vue qui ne prend pas en charge une clé unique, car certains champs peuvent être annulés ou la nature de la vue n'est pas indexable logiquement.

Dans ces cas, la "clé" peut être définie sur n'importe quelle colonne non nullable mais AsNoTracking () doit être utilisé avec chaque requête, sinon les enregistrements (dupliqués par clé) seront ignorés.

crokusek
la source
2
Juste pour réitérer l'importance de ceci avec les vues, j'ai une requête à partir d'une vue qui retourne 7 enregistrements uniques lorsqu'elle est exécutée via SSMS. Lorsqu'il est exécuté via EF, sans le modificateur AsNoTracking, j'obtiens le premier enregistrement, trois copies du deuxième et trois copies du troisième. Cela a pris beaucoup de coups de tête incrédules à corriger, et c'était en utilisant AsNoTracking qui l'a corrigé!
Ade
J'ai eu exactement le même problème lors de l'utilisation de Linq pour les entités lors de l'interrogation d'une vue sans clé primaire. Je n'ai découvert AsNoTracking qu'après une demi-journée de gratte-tête. Ce message sur le forum ASP.Net m'a finalement conduit à cela. forums.asp.net/t/…
red_dorian
6

Si vous avez quelque chose d'autre qui modifie la base de données (par exemple un autre processus) et devez vous assurer que vous voyez ces changements, utilisez AsNoTracking(), sinon EF peut vous donner la dernière copie que votre contexte avait à la place, il est donc bon d'utiliser généralement un nouveau contexte à chaque requête :

http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/

Andrew Pate
la source