web-dev-qa-db-fra.com

L'obtention d'entités avec AsNoTracking () désactive-t-elle l'appel automatique à DetectChanges ()?

J'ai appris à connaître ce concept de AsNoTracking(), DetectChanges() et AutoDetectChangesEnabled très récemment. Je comprends que lors de la récupération des enregistrements de la base de données via Entity Framework avec AsNoTracking() utilisé, Entity Framework ne suit pas les modifications apportées à ces enregistrements et la mise à jour de toute propriété de l'enregistrement récupéré échouera dans ce cas.

Ma question est de savoir si les enregistrements sont récupérés de cette manière, cela entraînera-t-il également la désactivation de l'appel automatique à DetectChanges () ou cela doit-il être fait explicitement en définissant:

Context.Configuration.AutoDetectChangesEnabled = false;

Veuillez également me faire savoir quel impact (en termes de performances) cela a-t-il si les deux actions sont effectuées lors de la récupération des données strictement à des fins de lecture seule:

Context.Configuration.AutoDetectChangesEnabled = false;
Context.Set<T>().AsNoTracking();
25
Sayan Pal

cela entraînera-t-il également la désactivation de l'appel automatique à DetectChanges ()

Non, ce ne sera pas le cas. Mais vous devez comprendre que AsNoTracking et DetectChanges n'ont rien à voir l'un avec l'autre (à part faire partie d'EF). Les objets récupérés avec AsNoTracking ne seront de toute façon jamais détectés, que AutoDetectChanges soit activé ou non. En outre, AsNoTracking fonctionne au niveau DbSet, AutoDetectChangesEnabled au niveau du contexte. Il serait mauvais qu'une méthode DbSet affecte l'ensemble du contexte.

ou que le [réglage AutoDetectChangesEnabled] doit être fait explicitement

Eh bien, vous ne devriez probablement pas désactiver AutoDetectChanges. Si vous le faites, vous devez savoir ce que vous faites.

quel impact (en termes de performances) a-t-il si les deux actions sont réalisées

Comme je l'ai dit, ils ne sont pas liés. Ils peuvent tous deux améliorer les performances à leur manière.

  • AsNoTracking est idéal si vous souhaitez récupérer des données en lecture seule. Il n'a pas d'effets secondaires (comme dans: son effet est clair)
  • Réglage AutoDetectChangesEnabled = false arrête les appels automatiques de DetectChanges (qui peuvent être nombreux), mais il a des effets secondaires dont vous devez être conscient. Extrait du livre de Lerman & Miller DbContext:

    Déterminer quand DetectChanges doit être appelé n'est pas aussi trivial qu'il y paraît. L'équipe Entity Framework vous recommande fortement de ne passer à l'appel manuel de DetectChanges que si vous rencontrez des problèmes de performances. Il est également recommandé de ne désactiver les DetectChanges automatiques que pour les sections de code peu performantes et de le réactiver une fois que la section en question a terminé son exécution.

31
Gert Arnold

Nous avons constaté que la définition de AutoDetectChangesEnabled = false Peut avoir des impacts de performance substantiels (c'est-à-dire un facteur 10).

Contexte: Notre système est entièrement composé d'objets de modèle EF qui utilisent des proxys de détection de changement. Autrement dit, tous nos champs de base de données et nos propriétés relationnelles sont déclarés comme virtuels. Nous avons également un modèle objet relativement profondément structuré. Autrement dit, l'objet A contient un ensemble d'objets B, qui à leur tour contiennent un ensemble d'objets C, etc. Nous avons observé que l'instanciation d'un nombre non trivial (> 100) de ces objets via une requête EF/LINQ coûte cher. Par exemple, dans un cas, l'instanciation de 250 objets a nécessité environ 2 secondes. Nous avons également observé que l'instanciation de la même structure, mais l'utilisation à la place d'objets anonymes nécessitait environ 25 ms. Enfin, nous avons observé que si nous définissions AutoDetectChangesEnabled = false, Nous pourrions utiliser à nouveau la requête instanciant les objets du modèle EF et la matérialisation était d'environ 25 ms.

Donc, au moins pour nous, il y avait des gains énormes à faire en le définissant faux. Nous utilisons un modèle d'unité de travail et nous indiquons explicitement si l'unité de travail est en lecture seule ou non. Pour une unité de travail en lecture seule, le réglage de AutoDetectChangesEnabled = false Est parfaitement sûr, car il n'y aura jamais de changement. En fait, nous avons ajouté cette modification à notre système deux ans après notre version initiale (il y avait donc de nombreuses unités préexistantes dans le code) et la modification n'a rien cassé du tout et a considérablement amélioré les performances.

Nous avons également expérimenté AsNoTracking() et nous avons constaté qu'il ne nous apportait pratiquement aucune augmentation des performances. Si je comprends bien, une requête avec AsNoTracking() signifie que les objets ne seront pas placés dans la carte d'identité, ce qui forcera EF à récupérer à nouveau l'objet à partir du disque s'il est référencé plusieurs fois dans le contexte (par exemple dans différentes requêtes). Il y a donc un inconvénient potentiel à AsNoTracking().

Détails d'implémentation:

  • Nous avons une sous-classe de DBContext qui fournit une grande partie de l'infrastructure de notre unité de travail
  • Notre unité de travail est essentiellement un emballage léger dans le contexte
  • Lorsqu'une unité de travail est allouée (généralement dans un bloc à l'aide du bloc ), elle reçoit l'un de ces contextes par injection (nous utilisons Castle/Windsor)
  • Pendant l'initialisation, l'unité d'oeuvre appelle une méthode sur le contexte dans laquelle AutoDetectChangesEnabled est défini sur false
  • Actuellement, nous faisons cela tout le temps car nous utilisons toujours des proxys de détection de changement et ils ne nécessitent pas AutoDetectChangesEnabled
  • Auparavant, nous ne le faisions que pour les unités de travail `` en lecture seule '', car si rien n'est modifié dans une UoW, il n'est pas nécessaire de détecter les changements (lorsque nous avons alloué une unité de travail, nous indiquons explicitement si elle est en lecture seule ou non)
  • -
20
Terry Coatta