Speichern von Änderungen und Verwalten von Parallelität (Entity Framework)

Standardmäßig implementiert Entity Framework ein Modell vollständiger Parallelität. Das bedeutet, dass Sperren zwischen einer Abfrage der Daten und deren Aktualisierung in der Datenquelle nicht aufrechterhalten werden. Entity Framework speichert Objektänderungen in der Datenbank, ohne die Parallelität zu überprüfen. Daher wird für Entitäten, für die ein hoher Grad an Parallelität nötig sein kann, empfohlen, dass die Entität in der konzeptionellen Ebene eine Eigenschaft mit dem Attribut ConcurrencyMode="fixed" definiert, wie im folgenden Beispiel gezeigt:

<Property Name="Status" Type="Byte" Nullable="false" ConcurrencyMode="Fixed" />

Bei der Verwendung dieses Attributs wird die Datenbank von Entity Framework vor dem Speichern von Änderungen in der Datenbank auf Änderungen geprüft. Konflikte verursachende Änderungen lösen eine OptimisticConcurrencyException aus. Weitere Informationen finden Sie unter Gewusst wie: Verwalten von Datenparallelität im Objektkontext (Entity Framework). Die Ausnahme OptimisticConcurrencyException kann auch auftreten, wenn Sie ein Entity Data Model definieren, das gespeicherte Prozeduren verwendet, um die Datenquelle zu aktualisieren. In diesem Fall wird die Ausnahme ausgelöst, wenn die gespeicherte Prozedur, die verwendet wird, um Updates auszuführen, meldet, dass keine (null) Zeilen aktualisiert wurden.

Wenn in solchen Hochparallelitätsszenarien Aktualisierungen vorgenommen werden, wird empfohlen, Refresh häufig aufzurufen. Wenn Sie Refresh aufrufen, steuert der RefreshMode, wie Änderungen weitergegeben werden. Die Option StoreWins führt dazu, dass Entity Framework alle Daten im Objektcache mit den entsprechenden Werten aus der Datenbank überschreibt. Umgekehrt ersetzt die Option ClientWins die ursprünglichen Werte im Cache mit den aktuellen Werten aus der Datenquelle. So wird sichergestellt, dass alle geänderten Daten im Objektcache erfolgreich in der Datenquelle gespeichert werden können, da Konflikte zwischen Änderungen an den Daten im Cache und denen in der Datenquelle vermieden werden.

Rufen Sie die Refresh-Methode auf, nachdem die SaveChanges-Methode aufgerufen wurde, wenn Updates der Datenquelle möglicherweise die Daten ändern, die zu anderen Objekten im Objektkontext gehören. Wird zum Beispiel im AdventureWorks Sales-Modell ein neues SalesOrderDetail eingefügt, löst dies eine Aktualisierung der Spalte SubTotal aus, damit in der Zwischensumme das neue Element berücksichtigt wird. Rufen Sie in diesem Fall die Refresh-Methode auf, und übergeben Sie das SalesOrderHeader-Objekt für die Bestellung. Dadurch wird sichergestellt, dass triggergenerierte Werte an das SalesOrderHeader-Objekt im Objektkontext zurückgesendet werden.

In Entity Framework werden die an den Objekten im Cache vorgenommenen Änderungen nachverfolgt. Wenn die Methode SaveChanges aufgerufen wird, versucht Entity Framework die Änderungen in der Datenquelle zusammenzuführen. SaveChanges kann mit einer OptimisticConcurrencyException fehlschlagen, wenn Datenänderungen im Objektcache mit Änderungen in Konflikt stehen, die in der Datenquelle vorgenommen wurden, nachdem die Objekte dem Cache hinzugefügt oder dort aktualisiert wurden. In diesem Fall wird die gesamte Transaktion zurückgesetzt. Wenn eine OptimisticConcurrencyException auftritt, sollte Refresh aufgerufen und angegeben werden, ob der Konflikt aufgelöst werden soll, indem die Daten in den Objektdaten beibehalten werden (ClientWins) oder ob der Objektcache mit den Daten aus der Datenquelle aktualisiert werden soll (StoreWins) (siehe folgendes Beispiel):

Try
    ' Try to save changes, which may cause a conflict. 
    Dim num As Integer = context.SaveChanges()
    Console.WriteLine("No conflicts. " & num.ToString() & " updates saved.")
Catch generatedExceptionName As OptimisticConcurrencyException
    ' Resolve the concurrency conflict by refreshing the 
    ' object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders)

    ' Save changes. 
    context.SaveChanges()
    Console.WriteLine("OptimisticConcurrencyException handled and changes saved")
End Try
try
{
    // Try to save changes, which may cause a conflict.
    int num = context.SaveChanges();
    Console.WriteLine("No conflicts. " +
        num.ToString() + " updates saved.");
}
catch (OptimisticConcurrencyException)
{
    // Resolve the concurrency conflict by refreshing the 
    // object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders);

    // Save changes.
    context.SaveChanges();
    Console.WriteLine("OptimisticConcurrencyException "
    + "handled and changes saved");
}

SaveChanges kann eine UpdateException generieren, wenn ein dem ObjectContext hinzugefügtes Objekt in der Datenquelle nicht erfolgreich erstellt wurde. Dies kann geschehen, wenn eine Zeile mit dem von der Beziehung angegebenen Fremdschlüssel bereits vorhanden ist. In diesem Fall können Sie das hinzugefügte Objekt mithilfe von Refresh im Objektkontext aktualisieren. Laden Sie stattdessen das Objekt mit dem Wert OverwriteChanges für MergeOption erneut.

Weitere Informationen zum Verwalten des Objektkontexts finden Sie unter Gewusst wie: Verwalten von Datenparallelität im Objektkontext (Entity Framework).

Möglicherweise ziehen Sie es vor, Transaktionen als Alternative zu vollständiger Parallelität zu verwenden. Weitere Informationen finden Sie unter Verwalten von Verbindungen und Transaktionen (Entity Framework).

In diesem Abschnitt

Gewusst wie: Verwalten von Datenparallelität im Objektkontext (Entity Framework)

Siehe auch

Konzepte

Arbeiten mit Objekten (Entity Framework)
Erstellen, Hinzufügen, Ändern und Löschen von Objekten (Entity Framework)