QueryTrackingBehavior in Entity Framework Core

In Entity Framework Core hat Microsoft eine eleganteres Feature eingebaut, um die Performance von Datenbank-Leseoperationen per No-Tracking zu steigern.

In Pocket speichern vorlesen Druckansicht
Lesezeit: 3 Min.
Von
  • Dr. Holger Schwichtenberg

In Entity Framework Core hat Microsoft eine eleganteres Feature eingebaut, um die Performance von Datenbank-Leseoperationen per No-Tracking zu steigern.

Der No-Tracking-Modus steigert die Performance beim Lesen von Datensätzen mit Entity Framework und Entity Framework Core erheblich. Leider mussten Softwareentwickler im klassischen Entity Framework immer daran denken, in jeder ihrer Abfragen AsNoTracking() zu verwenden. Das ist nur nicht lästig für Entwickler, sondern birgt zugleich auch die Gefahr des unabsichtlichen Vergessens. In meinen Beratungseinsätzen zur Performanceoptimierung von .NET-Anwendungen erlebe ich immer wieder, dass der No-Tracking-Modus nicht benutzt wurde. Im klassischen Entity Framework hat man für diese Situation eigene Lösungen gebraucht, zum Beispiel eine Abstraktion für den Zugriff DbSet<T>, die den No-Tracking-Modus jedes Mal automatisch aktiviert hat.

In Entity Framework Core hat Microsoft seit Version 1.0 eine elegantere Lösung eingebaut: Entwickler können den gesamten Entity-Framework-Core-Kontext in einen No-Tracking-Modus schalten. Dafür gibt es in der Klasse Microsoft.EntityFrameworkCore.DbContext im Unterobjekt ChangeTracker die Aufzählungseigenschaft QueryTrackingBehavior: Sie steht im Standard auf QueryTrackingBehavior.TrackAll, das heißt, das Tracking ist aktiviert. Wenn Entwickler sie jedoch auf QueryTrackingBehavior.NoTracking umstellen, werden alle Abfragen im No-Tracking-Modus ausgeführt, auch ohne den Einsatz der Erweiterungsmethode AsNoTracking(). Für diesen No-Tracking-Grundmodus gibt es dann eine neue Erweiterungsmethode AsTracking(), um einzelne Abfragen im Tracking-Modus auszuführen (siehe folgendes Codebeispiel).

Console.WriteLine("Grundeinstellung TrackAll. Abfrage mit AsNoTracking()");
using (WWWingsContext ctx = new WWWingsContext())
{
ctx.ChangeTracker.QueryTrackingBehavior =
QueryTrackingBehavior.TrackAll; // Standard
var flugSet = ctx.FlugSet.AsNoTracking().ToList();
var flug = flugSet[0];
Console.WriteLine(flug + " Zustand: " +
ctx.Entry(flug).State); // Detached
flug.FreiePlaetze--;
Console.WriteLine(flug + " Zustand: " +
ctx.Entry(flug).State); // Modified
int anz = ctx.SaveChanges();
}

Console.WriteLine("Grundeinstellung NoTracking.");
using (WWWingsContext ctx = new WWWingsContext())
{
ctx.ChangeTracker.QueryTrackingBehavior =
QueryTrackingBehavior.NoTracking; // NoTracking
var flugSet = ctx.FlugSet.ToList();
var flug = flugSet[0];
Console.WriteLine(flug + " Zustand: " +
ctx.Entry(flug).State); // Unchanged
flug.FreiePlaetze--;
Console.WriteLine(flug + " Zustand: " +
ctx.Entry(flug).State); // Modified
int anz = ctx.SaveChanges();
}

Console.WriteLine("Grundeinstellung NoTracking. Abfrage mit
AsTracking()");
using (WWWingsContext ctx = new WWWingsContext())
{
ctx.ChangeTracker.QueryTrackingBehavior =
QueryTrackingBehavior.NoTracking; // NoTracking
var flugSet = ctx.FlugSet.AsTracking().ToList();
var flug = flugSet[0];
Console.WriteLine(flug + " Zustand: " +
ctx.Entry(flug).State); // Unchanged
flug.FreiePlaetze--;
Console.WriteLine(flug + " Zustand: " +
ctx.Entry(flug).State); // Modified
int anz = ctx.SaveChanges();
}

Mehr Praxistipps zu Entity Framework Core findet man in meinem E-Book "Moderne Datenzugriffslösungen mit Entity Framework Core" (17,50 US-Dollar). ()