In diesem Post sehen wir uns das Changetracking von EF Core einmal genauer an.

Wir starten damit, was Changetracking grundsätzlich tut.

Aufgabe des Changetrackings in EF core

EF core hilft uns dabei Code zu schreiben, der die Datenbank abstrahiert und die Konzepte der Datenbank aus dem direkten Code heraushält.

Dies gilt nicht nur für die Repräsentation (Klassen mit Navigationproperties anstelle von Fremdschlüsseln usw.) sondern eben auch für die Query API.

Um Änderungen an den Entitäten der Datenbank zu erkennen nutzt Entity Framework das Konzept des Changetrackings. 

Die Idee vom Changetracking ist als unsere Commands gegen die Datenbank mit der EF core API zu abstrahieren.

Wie funktioniert Changetracking

Das Changetracking wird immer dann aktiviert wenn wir eine der CRUD Operationen auf einer Instanz unseres DbContextes aufrufen.

Was bedeutet dies?
Das ChangeTracking weist jeder Entität einen Eintrag bzw. einen Zustand zu.

Dieser Zustand kann einer der folgenden 5 sein:

  • Unchanged 
  • Modified
  • Added
  • Deleted
  • Detached

Anhand dieses Zustands wird bestimmt, welche Art von Datenbank commands generiert werden.

CRUD Operationen und Changetracking

READ Operation

Nutzen wir eine READ Operation wird das ChangeTracking automatisch für jede so zurückgegebene Entität aktiviert. 

Der jeweilige Zustand ist dann Unchanged, da nur lesend zugegriffen wurde. Allerdings können die Entities so für Updates oder Deletes verwendet werden.

Dies lässt sich unterbinden durch die AsNoTracking Methode aus dem Namespace Microsoft.EntityFrameworkCore und ist essentiell für performance bei nur lesenden Operationen. 

Mit der Nutzung der AsNoTracking Methode ist zu beachten, dass die so abgerufenen Entitäten NICHT für Updates und als Navigationproperties auf Adds verwendet werden dürfen! (siehe Beispiel)

using (var session = new LeantrainingDbContext())
{ var round = session.Rounds.AsNoTracking().First(); round.Start = DateTime.Now; session.Update(round); session.SaveChanges(); // throws Exception --> Untracked Entity kann nicht // modifiziert werden
}
// oder auch verboten
using (var session = new LeantrainingDbContext())
{ var round = session.Rounds.AsNoTracking().First(); var product = new Product { Round = round, Start = DateTime.Now }; session.Add(product); // Exception! --> Entity mit Id {{ round.Id }} existiert bereits. session.SaveChanges();
}

Im zweiten Beispiel werden zwei Entities zum Add hinzugefügt. Einmal das Product und die Round, da beide noch den Status Detached haben.

Die Round hat jedoch eine Id, und diese ist bereits in der Datenbank vorhanden. Die Entität kommt ja schließlich aus der Datenbank.

Um dies zu umgehen kann man entweder auf AsNoTracking verzichten oder die Id auf -1 oder 0 setzen, dann vergibt EF core auf der Datenbank selbst eine Id.

DAS WICHTIGSTE AUS DIESEM BEISPIEL IST JEDOCH:
ChangeTracking ist nur in Memory und macht keine Datenbankabfragen bezüglich der Entitäten, es bereitet Commands nur anhand des States vor und das müssen wir korrekt kontrollieren.

CUD am Beispiel Create

Wenn wir eine Entität in die Datenbank einfügen wollen, dann nutzen wir ein INSERT COMMAND. Mit EF Core nutzen wir die Add Methode auf der DbSet<T> Property des DbContexts. 

Dies fügt der Entität dann den Zustand Added hinzu. Dieser wird aber erst hinzugefügt, wenn wir die Added Methode aufrufen. Vorher ist der Zustand Detached.

Dies können wir wie folgt überprüfen:

using (var session = new LeantrainingDbContext())
{ var product = new Product { Start = DateTime.Now }; var entry = session.Entry(product); // entry.State == "Detached" session.Products.Add(product); // session.Entry(product).State == "Added"
}

Wir nutzen wieder die Beispielapplikation für diesen Code…

Wir sehen also, dass wir eine neue Instanz der Product Entität erstellen.
Wenn wir auf der DbContext Instanz dann die Entry Methode aufrufen erhalten wir eine EntityEntry<Product> Objekt zurück.

Auf diesem können wir den Typ der Entität abfragen sowie den State.

Vor dem Aufruf der session.Products.Add(product); Methode ist der Status dementsprechend Detached, da es keine Interaktion mit dem Context gab.

Nach dem Aufruf der Methode ist der Status dann Added, entsprechend der Add Methode. 

Dieses Prinzip gilt analog für die Update und Delete Methoden.

Mehr Themen zu EF core findest du hier:

Entity Framework Core

Categories: ef-core-de

0 Comments

Leave a Reply