Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Beim Abfragen können Sie Daten aus der Datenbank lesen, und das Speichern von Daten bedeutet, der Datenbank neue Entitäten hinzuzufügen, Entitäten zu entfernen oder die Eigenschaften vorhandener Entitäten auf irgendeine Weise zu ändern. Entity Framework Core (EF Core) unterstützt zwei grundlegende Ansätze zum Speichern von Daten in der Datenbank.
Ansatz 1: Änderungsnachverfolgung und SaveChanges
In vielen Szenarien muss Ihr Programm einige Daten aus der Datenbank abfragen, einige Änderungen daran vornehmen und diese Änderungen wieder speichern. dies wird manchmal als "Arbeitseinheit" bezeichnet. Nehmen wir beispielsweise an, dass Sie über eine Reihe von Blogs verfügen, und Sie möchten die Url Eigenschaft einer davon ändern. In EF erfolgt dies in der Regel wie folgt:
using (var context = new BloggingContext())
{
var blog = await context.Blogs.SingleAsync(b => b.Url == "http://example.com");
blog.Url = "http://example.com/blog";
await context.SaveChangesAsync();
}
Der obige Code führt die folgenden Schritte aus:
- Es verwendet eine normale LINQ-Abfrage, um eine Entität aus der Datenbank zu laden (siehe Abfragedaten). EF-Abfragen werden standardmäßig nachverfolgt, was bedeutet, dass EF die geladenen Entitäten in seiner internen Änderungsverfolgung nachverfolgt.
- Die geladene Entitätsinstanz wird wie gewohnt durch Zuweisen einer .NET-Eigenschaft bearbeitet. EF ist in diesem Schritt nicht beteiligt.
- Schließlich wird DbContext.SaveChanges() aufgerufen. An diesem Punkt erkennt EF automatisch alle Änderungen, indem die Entitäten mit einer Momentaufnahme verglichen werden, sobald sie geladen wurden. Alle erkannten Änderungen werden in der Datenbank beibehalten; bei Verwendung einer relationalen Datenbank umfasst dies in der Regel das Senden von SQL
UPDATEzum Aktualisieren der relevanten Zeilen.
Beachten Sie, dass der oben beschriebene typische Aktualisierungsvorgang für vorhandene Daten, aber ähnliche Prinzipien für das Hinzufügen und Entfernen von Entitäten gelten. Sie interagieren mit der Änderungsverfolgung von EF, indem Sie DbSet<TEntity>.Add und Remove aufrufen, wodurch die Änderungen nachverfolgt werden. EF wendet dann alle nachverfolgten Änderungen in der Datenbank an, wenn SaveChanges() aufgerufen wird (z. B. über SQL INSERT und DELETE bei Verwendung einer relationalen Datenbank).
SaveChanges() bietet die folgenden Vorteile:
- Sie müssen keinen Code schreiben, um nachzuverfolgen, welche Entitäten und Eigenschaften geändert wurden . EF führt dies automatisch für Sie durch und aktualisiert nur diese Eigenschaften in der Datenbank, wodurch die Leistung verbessert wird. Stellen Sie sich vor, wenn Ihre geladenen Entitäten an eine UI-Komponente gebunden sind, sodass Benutzer beliebige Eigenschaften ändern können. EF nimmt die Last, herauszufinden, welche Entitäten und Eigenschaften tatsächlich geändert wurden.
- Das Speichern von Änderungen an der Datenbank kann manchmal kompliziert sein! Wenn Sie beispielsweise einen Blog und einige Beiträge für diesen Blog hinzufügen möchten, müssen Sie möglicherweise den datenbankgenerierten Schlüssel für den eingefügten Blog abrufen, bevor Sie die Beiträge einfügen können (da sie auf den Blog verweisen müssen). EF erledigt all dies für Sie und nimmt die Komplexität weg.
- EF kann Nebenläufigkeitsprobleme erkennen, z. B. wenn eine Datenbankzeile von einer anderen Person zwischen Ihrer Abfrage und SaveChanges() geändert wurde. Weitere Details sind in Parallelitätskonflikten verfügbar.
- Bei Datenbanken, die dies unterstützen, fasst SaveChanges() mehrere Änderungen automatisch in einer Transaktion zusammen, um sicherzustellen, dass Ihre Daten konsistent bleiben, wenn ein Fehler auftritt. Weitere Details finden Sie in Transaktionen.
- SaveChanges() fasst in vielen Fällen mehrere Änderungen zusammen, wodurch die Anzahl der Datenbankzugriffe erheblich reduziert und die Leistung deutlich verbessert wird. Weitere Details sind in Efficient Updating verfügbar.
Weitere Informationen und Codebeispiele zur grundlegenden SaveChanges() Verwendung finden Sie unter "Basic SaveChanges". Weitere Informationen zur Änderungsnachverfolgung von EF finden Sie in der Übersicht über die Änderungsnachverfolgung.
Ansatz 2: ExecuteUpdate und ExecuteDelete ("Massenupdate")
Während die Änderungsnachverfolgung und SaveChanges() eine leistungsstarke Möglichkeit zum Speichern von Änderungen sind, haben sie bestimmte Nachteile.
Zunächst erfordert SaveChanges(), dass Sie alle Entitäten abfragen und nachverfolgen, die Sie ändern oder löschen werden. Wenn Sie beispielsweise alle Blogs löschen müssen, deren Bewertung unter einem bestimmten Schwellenwert liegt, müssen Sie eine potenziell große Anzahl von Zeilen abfragen, materialisieren und nachverfolgen, und für jede einzelne davon von SaveChanges() eine DELETE-Anweisung generieren lassen. Relationale Datenbanken bieten eine weitaus effizientere Alternative: Ein einzelner DELETE Befehl kann gesendet werden, wobei angegeben wird, welche Zeilen über eine WHERE Klausel gelöscht werden sollen, aber das SaveChanges() Modell lässt dies nicht zu.
Um dieses Szenario "Massenaktualisierung" zu unterstützen, können Sie folgendes verwenden ExecuteDelete :
context.Blogs.Where(b => b.Rating < 3).ExecuteDelete();
Auf diese Weise können Sie eine SQL-Anweisung DELETE über normale LINQ-Operatoren ausdrücken , ähnlich wie eine normale LINQ-Abfrage, wodurch die folgende SQL-Anweisung für die Datenbank ausgeführt wird:
DELETE FROM [b]
FROM [Blogs] AS [b]
WHERE [b].[Rating] < 3
Dies wird sehr effizient in der Datenbank ausgeführt, ohne Daten aus der Datenbank zu laden oder die Änderungsverfolgung von EF einzubeziehen.
ExecuteUpdate Auf ähnliche Weise können Sie eine SQL-Anweisung UPDATE ausdrücken.
Auch wenn Sie entitäten nicht in massenweise ändern, wissen Sie möglicherweise genau, welche Eigenschaften welche Entität Sie ändern möchten. Die Verwendung der Änderungsnachverfolgungs-API zum Ausführen der Änderung kann übermäßig komplex sein, erfordert das Erstellen einer Entitätsinstanz, das Nachverfolgen über Attach, das Vornehmen Ihrer Änderungen und schließlich das Aufrufen SaveChanges(). Für solche Szenarien können ExecuteUpdate und ExecuteDelete eine deutlich einfachere Möglichkeit sein, denselben Vorgang auszudrücken.
Schließlich verursachen sowohl die Änderungsnachverfolgung als auch SaveChanges() selbst einen bestimmten Laufzeitaufwand. Wenn Sie eine Hochleistungsanwendung schreiben, ermöglichen Ihnen ExecuteUpdate und ExecuteDelete, beide Komponenten zu vermeiden und die gewünschte Anweisung effizient zu generieren.
Beachten Sie jedoch, dass ExecuteUpdate und ExecuteDelete auch bestimmte Einschränkungen aufweisen.
- Diese Methoden werden sofort ausgeführt, und derzeit können keine Batchvorgänge mit anderen Vorgängen ausgeführt werden. Andererseits kann SaveChanges() mehrere Vorgänge zusammenführen.
- Da die Änderungsnachverfolgung nicht einbezogen wird, liegt es in Ihrer Verantwortung, genau zu wissen, welche Entitäten und Eigenschaften geändert werden müssen. Dies kann eine manuellere Codenachverfolgung auf niedriger Ebene bedeuten, was geändert werden muss und was nicht.
- Da die Änderungsnachverfolgung nicht einbezogen wird, wenden diese Methoden beim Beibehalten von Änderungen nicht automatisch die Parallelitätssteuerung an. Sie können jedoch weiterhin explizit eine
WhereKlausel hinzufügen, um die Parallelitätssteuerung selbst zu implementieren. - Derzeit wird nur das Aktualisieren und Löschen unterstützt. Das Einfügen muss über DbSet<TEntity>.Add und SaveChanges() erfolgen.
Weitere Informationen und Codebeispiele finden Sie unter ExecuteUpdate und ExecuteDelete.
Zusammenfassung
Im Folgenden sind einige Richtlinien für die Verwendung dieses Ansatzes aufgeführt. Beachten Sie, dass es sich hierbei nicht um absolute Regeln handelt, aber eine nützliche Faustregel bereitstellen:
- Wenn Sie im Voraus nicht wissen, welche Änderungen vorgenommen werden, verwenden Sie
SaveChanges; es erkennt automatisch, welche Änderungen angewendet werden müssen. Beispielszenarien:- "Ich möchte einen Blog aus der Datenbank laden und ein Formular anzeigen, das es dem Benutzer ermöglicht, ihn zu ändern"
- Wenn Sie ein Diagramm von Objekten (d. h. mehrere miteinander verbundene Objekte) bearbeiten müssen, verwenden Sie
SaveChanges; es ermittelt die richtige Reihenfolge der Änderungen und wie alles miteinander verknüpft werden kann.- "Ich möchte einen Blog aktualisieren, einige seiner Beiträge ändern und andere löschen"
- Wenn Sie eine potenziell große Anzahl von Entitäten basierend auf einem bestimmten Kriterium ändern möchten, verwenden
ExecuteUpdateundExecuteDelete. Beispielszenarien:- "Ich möchte allen Mitarbeitern eine Erhöhung geben"
- "Ich möchte alle Blogs löschen, deren Name mit X beginnt"
- Wenn Sie bereits genau wissen, welche Entitäten Sie ändern möchten und wie Sie sie ändern möchten, verwenden Sie
ExecuteUpdateundExecuteDelete. Beispielszenarien:- "Ich möchte den Blog löschen, dessen Name 'Foo' ist"
- "Ich möchte den Namen des Blogs mit id 5 in "Bar" ändern.