Entity Framework: Der ChangeTracker

Lies in den Artikel rein und unten bekommst Du ein unschlagbares Angebot!

Wenn Sie Daten etwa aus den Tabellen einer Datenbank in ein Entity Data Model geladen haben, finden Sie dort einige Funktionen für den Umgang mit den enthaltenen Daten vor. Ein sehr wichtiges Element ist dabei der ChangeTracker. Auch wenn Sie mit der SaveChanges-Methode automatisch alle Änderungen im Entity Data Model erkennen und diese in die Datenbank übertragen können, so treten doch Fälle auf, in denen Sie zuvor prüfen wollen, welche Änderungen überhaupt im Entity Data Model vorgenommen wurden – und ob diese in die Datenbank übernommen oder vielleicht sogar verworfen werden sollen.

Wenn Sie eine Anwendung bauen, wie wir sie in den letzten Ausgaben verwendet haben, dann bezieht diese ihre Daten aus den Tabellen eines SQL Servers und stellt diese in einem Entity Data Model bereit. Die Elemente des Entity Data Models binden Sie dann an die Benutzeroberfläche und die dort befindlichen Steuer-elemente.

Nun können nach dem Anzeigen der Daten in einem Fenster zum Bearbeiten verschiedene Fälle auftreten: Sie ändern ein oder mehrere Felder eines Datensatzes, fügen einen neuen Datensatz hinzu oder löschen einen Datensatz. Diese Änderungen liegen dann im Entity Data Model vor, aber werden nicht automatisch in die Datenbank übertragen. Das erledigen Sie erst, wenn Sie die SaveChanges-Methode des Datenbankkontextes aufrufen. SaveChanges ist effizient, denn es prüft, ob Änderungen vorliegen und speichert nur die geänderten Elemente in der Datenbank.

Was aber geschieht, wenn Sie beispielsweise erfahren wollen, ob an einem bestimmten Datensatz Änderungen vorgenommen wurden Für ein Fenster mit Minimalanforderungen benötigen Sie diese Information nicht, denn Sie können die Änderungen ja einfach in der Datenbank speichern. Wenn Sie dem Benutzer jedoch ein paar weitere Features wie etwa eine Schaltfläche zum Verwerfen der Änderungen zur Verfügung stellen wollen, kann es schon interessant sein, ob der Benutzer überhaupt schon Änderungen am aktuellen Datensatz vorgenommen hat. Dabei könnten Sie die Information, ob der Datensatz bereits geändert wurde, etwa dazu nutzen, die Abbrechen– oder Verwerfen-Schaltfläche nur zu aktivieren, wenn der Benutzer bereits Änderungen vorgenommen hat – oder wenn er soeben einen neuen Datensatz angelegt hat, der ja mitunter auch verworfen werden könnte.

Und hier kommt der ChangeTracker von Entity Framework ins Spiel. Dabei handelt es sich um eine Klasse, die zum Beispiel den Zugriff auf alle Elemente mit einem bestimmten Status zulässt – beispielsweise geändert oder nicht geändert. In diesem Artikel schauen wir uns nun an, wie Sie mit dem ChangeTracker von Entity Framework arbeiten können.

Beispielprojekt

Als Beispielprojekt verwenden wir ein Projekt auf Basis der Vorlage Visual Basic|Windows Desktop|WPF-App namens ChangeTracker. Dieser haben wir ein Entity Data Model mit der Methode aus der Artikelreihe Von Access zu Entity Framework hinzugefügt und eine SQL Server-Datenbank damit erstellt. Um die SQL Server-Datenbank auf ihrem Rechner zu erstellen, rufen Sie die Anweisung Update-Database in der Paket-Manager-Konsole auf. Dadurch wird eine Datenbank auf Basis der in der Datei App.config angegebenen Verbindungszeichenfolge erstellt, die Sie gegebenenfalls noch anpassen können. Die verschiedenen Beispielcodes der folgenden Abschnitte finden Sie hinter den Ereignismethoden der Schaltflächen des Fensters MainWindow.xaml.

Die ChangeTracker-Klasse

Die ChangeTracker-Klasse referenzieren über die gleichnamige Eigenschaft der Datenbankkontext-Klasse, die in unserem Beispielen meist dbContext genannt wird. Mit dieser Klasse können Sie den Zustand jedes der Elemente des aktuellen Datenbankkontexts nachverfolgen. Jeder der Einträge hat einen Wert für die Eigenschaft EntityState. Die möglichen Werte lauten:

  • Added: Hinzugefügtes Element, das noch nicht in der Datenbank existiert
  • Modified: Geändertes Element, dessen Änderungen noch nicht in die Datenbank übertragen wurden
  • Deleted: Gelöschtes Element, das noch in der Datenbank existiert
  • Unchanged: Nicht geändertes Element
  • Detached: Nicht verbundenes, also nicht zu einem DbSet gehörendes Element. Dieses wird auch nicht vom ChangeTracker verfolgt.

Beispiele zur ChangeTracker-Klasse

Wir schauen uns die verschiedenen Zustände an einfachen Beispielen an. Dazu fügen wir der Klasse MainWindow.xaml.vb zunächst die folgenden Namespaces hinzu:

Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure

Danach erstellen wir die folgende Ereignismethode für die erste Schaltfläche btnUnveraendert. Hier füllen wir die Variable dbContext mit einer neuen Instanz des Datenbankkontextes und füllen das Objekt Kunde des Typs Kunde mit dem ersten Eintrag der Liste Kunden des Datenbankbankkontextes:

Private Sub btnUnveraendert_Click(sender As Object, e As RoutedEventArgs)
     Dim dbContext As BestellverwaltungContext
     Dim Element As EntityEntry
     Dim Kunde As Kunde
     dbContext = New BestellverwaltungContext
     Kunde = dbContext.Kunden.First()

Danach folgt der erste Zugriff auf den ChangeTracker. Dabei durchlaufen wir dessen Entries-Auflistung und referenzieren das aktuelle Element jeweils mit der Variablen Element, die übrigens den Typ EntityEntry aufweist (dafür auch der Verweis auf den Namespace). Anschließend geben wir für jeden Eintrag zwei Informationen aus – den Namen des Elementtyps und den Zustand. Um den Namen des Elementtyps zu erhalten, referenzieren wir zunächst die in Element enthaltene Entität mit der Eigenschaft Entity und ermitteln den Namen des Typs mit GetType().Name. Den Zustand dieses Eintrags liefert die Eigenschaft State des EntityEntry-Elements:

     For Each Element In dbContext.ChangeTracker.Entries
         Debug.Print("Elementname: " + Element.Entity.GetType().Name + " Status: " + Element.State.ToString())
     Next
End Sub

Das Ergebnis sieht schließlich wie in Bild 1 aus. Der Typ Kunde wird korrekt erkannt und auch der Status entspricht mit Unchanged den Erwartungen.

Ausgabe von Typ und Status einer Entität

Bild 1: Ausgabe von Typ und Status einer Entität

ChangeTracker verfolgt alle Elementtypen

Wir fügen eine Variable für ein Element eines weiteren Elementtypen namens Anrede hinzu und lesen auch hier den ersten Eintrag aus – in diesem Fall aus der Liste Anreden:

Dim Anrede As Anrede
...
Anrede = dbContext.Anreden.First()

Die Ausgabe im Ausgabefenster sieht nach dem erneuten Start der Anwendung dem Betätigen der Schaltfläche wie folgt aus:

Elementname: Kunde Status: Unchanged
Elementname: Anrede Status: Unchanged

Wir sehen also, dass die Entries-Auflistung der ChangeTracker-Klasse Elemente aller Typen umfasst – sie müssen nur in den Speicher geladen sein.

 

Schreibe einen Kommentar