Welchen Unterschied macht .AsNoTracking ()?

227

Ich habe eine Frage zur .AsNoTracking()Erweiterung, da dies alles ziemlich neu und ziemlich verwirrend ist.

Ich verwende einen Kontext pro Anfrage für eine Website.

Viele meiner Entitäten ändern sich nicht und müssen nicht nachverfolgt werden. Ich habe jedoch das folgende Szenario, in dem ich nicht sicher bin, was in die Datenbank gelangt oder ob dies in diesem Fall einen Unterschied macht.

Dieses Beispiel mache ich gerade:

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

Dies ist das gleiche wie oben, jedoch wird das .AsNoTracking()aus Schritt 1 entfernt:

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

Die Schritte 1 und 2 verwenden denselben Kontext, treten jedoch zu unterschiedlichen Zeiten auf. Was ich nicht herausfinden kann, ist, ob es einen Unterschied gibt. Da es sich bei Schritt 2 um ein Update handelt, werden beide ohnehin zweimal in die Datenbank gelangen.

Kann mir jemand sagen, was der Unterschied ist?

dotnetnoob
quelle

Antworten:

186

Der Unterschied besteht darin, dass der abgerufene Benutzer im ersten Fall nicht vom Kontext erfasst wird. Wenn Sie den Benutzer also wieder in der Datenbank speichern möchten, müssen Sie ihn anhängen und den korrekten Status des Benutzers festlegen, damit EF weiß, dass der vorhandene Benutzer aktualisiert werden soll anstatt einen neuen einzufügen. Im zweiten Fall müssen Sie dies nicht tun, wenn Sie den Benutzer mit derselben Kontextinstanz laden und speichern, da der Verfolgungsmechanismus dies für Sie erledigt.

Ladislav Mrnka
quelle
1
Können wir die gleichen Vorteile für anonyme Klassen in ausgewählten Abfragen erhalten, z. B. context.Users.Select (u => new {Name = u.Name})? Vielen Dank.
Dilhan Jayathilake
6
@ DilhanJayathilake: Anonyme Klassen repräsentieren nicht die Entität selbst, daher haben sie keine Nachverfolgung.
Ladislav Mrnka
1
Da EF6 den Entitätsschlüssel in einer Ansicht manchmal falsch ableitet, ignoriert AsNoTracking () den Schlüssel und ist daher eine Alternative zum manuellen Fixieren des Schlüssels (vorausgesetzt, andere Vorteile des Schlüssels sind nicht erforderlich).
Crokusek
4
Beachten Sie auch, dass der größte Effekt von AsNoTracking darin besteht, dass das verzögerte Laden nicht funktioniert
Douglas Gaskell,
169

Siehe diese Seite Entity Framework und AsNoTracking

Was AsNoTracking macht

Entity Framework bietet eine Reihe von Optionen zur Leistungsoptimierung, mit denen Sie die Leistung Ihrer Anwendungen optimieren können. Eine dieser Abstimmungsoptionen ist .AsNoTracking(). Mit dieser Optimierung können Sie festlegen Entity Framework, dass die Ergebnisse einer Abfrage nicht verfolgt werden sollen. Dies bedeutet, dass Entity Frameworkkeine zusätzliche Verarbeitung oder Speicherung der Entitäten durchgeführt wird, die von der Abfrage zurückgegeben werden. Dies bedeutet jedoch auch, dass Sie diese Entitäten nicht aktualisieren können, ohne sie erneut dem Tracking-Diagramm zuzuordnen.

Durch die Verwendung von AsNoTracking können erhebliche Leistungssteigerungen erzielt werden

Moji
quelle
11
Es scheint, dass die Gewinne manchmal ausgeglichen werden können: stackoverflow.com/questions/9259480/…
Fabrice
3
Mein Leistungsgewinn mit einer komplexen Abfrage, die eine Eltern-Kind-Beziehung mit Include in einem Schritt lädt, betrug ungefähr 50%
Karl
51

Kein Tracking von LINQ zu Entities-Abfragen

Die Verwendung von AsNoTracking () wird empfohlen, wenn Ihre Abfrage für Lesevorgänge vorgesehen ist. In diesen Szenarien erhalten Sie Ihre Entitäten zurück, diese werden jedoch nicht von Ihrem Kontext verfolgt. Dies gewährleistet eine minimale Speichernutzung und eine optimale Leistung

Vorteile

  1. Verbesserte Leistung gegenüber regulären LINQ-Abfragen.
  2. Vollständig materialisierte Objekte.
  3. Am einfachsten mit in die Programmiersprache integrierter Syntax zu schreiben.

Nachteile

  1. Nicht für CUD-Operationen geeignet.
  2. Bestimmte technische Einschränkungen, wie z. B.: Muster, die DefaultIfEmpty für OUTER JOIN-Abfragen verwenden, führen zu komplexeren Abfragen als einfache OUTER JOIN-Anweisungen in Entity SQL.
  3. Sie können LIKE immer noch nicht für den allgemeinen Mustervergleich verwenden.

Weitere Infos hier:

Leistungsüberlegungen für Entity Framework

Entity Framework und NoTracking

NullReference
quelle
10

Mit AsNoTracking () kann die Anforderung "Eindeutiger Schlüssel pro Datensatz" in EF umgangen werden (in anderen Antworten nicht explizit erwähnt).

Dies ist äußerst hilfreich, wenn Sie eine Ansicht lesen, die keinen eindeutigen Schlüssel unterstützt, da möglicherweise einige Felder nullwertfähig sind oder die Art der Ansicht nicht logisch indizierbar ist.

In diesen Fällen kann der "Schlüssel" auf eine beliebige nicht nullbare Spalte gesetzt werden, aber dann muss AsNoTracking () für jede Abfrage verwendet werden, da sonst Datensätze (nach Schlüssel dupliziert) übersprungen werden.

crokusek
quelle
2
Um die Wichtigkeit dieses Aspekts bei Ansichten zu wiederholen, habe ich eine Abfrage aus einer Ansicht, die 7 eindeutige Datensätze zurückgibt, wenn sie über SSMS ausgeführt wird. Bei Ausführung über EF ohne den Modifikator AsNoTracking erhalte ich den ersten Datensatz, drei Kopien des zweiten und drei Kopien des dritten. Das Reparieren erforderte eine Menge ungläubiger Kopfkratzer, und es wurde AsNoTracking verwendet, um das Problem zu beheben!
Ade
Ich hatte genau das gleiche Problem, als ich Linq to Entities verwendete, während ich eine Ansicht ohne Primärschlüssel abfragte. Erst nach einem halben Tag Kopfkratzen erfuhr ich von AsNoTracking. Dieser ASP.Net-Forumsbeitrag führte mich schließlich dazu. forums.asp.net/t/…
red_dorian
6

Wenn Sie etwas anderes haben, das die Datenbank ändert (z. B. einen anderen Prozess) und sicherstellen müssen, dass Sie diese Änderungen sehen, verwenden Sie AsNoTracking(), andernfalls gibt EF Ihnen möglicherweise die letzte Kopie, die Ihr Kontext stattdessen hatte. Daher ist es gut, normalerweise bei jeder Abfrage einen neuen Kontext zu verwenden ::

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

Andrew Pate
quelle