Freigeben über


Behandeln von Fehlern bei Transaktionscommits

Hinweis

Nur EF6.1 und höher: Die Features, APIs usw., die auf dieser Seite erläutert werden, wurden in Entity Framework 6.1 eingeführt. Wenn Sie eine frühere Version verwenden, gelten manche Informationen nicht.

Im Rahmen von 6.1 führen wir ein neues Feature zur Ausfallsicherheit von Verbindungen für EF ein, nämlich die Möglichkeit, vorübergehende Verbindungsfehler auf die Bestätigung von Transaktions-Commits zu erkennen und automatisch wiederherzustellen. Die vollständigen Einzelheiten des Szenarios werden am besten im Blogbeitrag SQL Datenbankkonnektivität und das Idempotenz-Problem beschrieben. Zusammengefasst ist das Szenario, dass es zwei mögliche Ursachen gibt, wenn eine Ausnahme während eines Transaktionscommits ausgelöst wird:

  1. Fehler beim Transaktionscommit auf dem Server
  2. Der Transaktionscommit war auf dem Server erfolgreich, aber ein Verbindungsproblem verhinderte, dass die Erfolgsbenachrichtigung den Client erreichte.

Wenn die erste Situation auftritt, kann die Anwendung oder der Benutzer den Vorgang wiederholen, aber wenn die zweite Situation auftritt, sollten Wiederholungen vermieden werden, und die Anwendung kann automatisch wiederhergestellt werden. Die Herausforderung besteht darin, dass die Anwendung nicht den richtigen weiteren Handlungsverlauf auswählen kann, ohne dass sie erkennt kann, warum während des Commits eine Ausnahme gemeldet wurde. Mit dem neuen Feature in EF 6.1 kann EF dies in der Datenbank überprüfen, nämlich ob die Transaktion erfolgreich war, und die richtige weitere Vorgehensweise transparent auswählen.

Verwenden der Funktion

Um das Feature zu aktivieren, müssen Sie einen Aufruf von SetTransactionHandler in den Konstruktor Ihrer DbConfiguration einschließen. Wenn Sie mit DbConfiguration nicht vertraut sind, finden Sie mehr dazu unter codebasierte Konfiguration. Dieses Feature kann in Kombination mit den automatischen Wiederholungen verwendet werden, die wir in EF6 eingeführt haben. Dies hilft bei der Situation, in der die Transaktion aufgrund eines vorübergehenden Fehlers tatsächlich nicht auf dem Server commiten konnte:

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;

public class MyConfiguration : DbConfiguration  
{
  public MyConfiguration()  
  {  
    SetTransactionHandler(SqlProviderServices.ProviderInvariantName, () => new CommitFailureHandler());  
    SetExecutionStrategy(SqlProviderServices.ProviderInvariantName, () => new SqlAzureExecutionStrategy());  
  }  
}

Wie Transaktionen verfolgt werden

Wenn das Feature aktiviert ist, fügt EF automatisch eine neue Tabelle zur Datenbank mit dem Namen __Transactionshinzu. Jedes Mal, wenn eine Transaktion von EF erstellt wird, wird eine neue Zeile in diese Tabelle eingefügt, und diese Zeile wird auf ihr Vorhandensein überprüft, wenn während des Commits ein Transaktionsfehler auftritt.

Obwohl EF Anstrengungen unternimmt, Zeilen aus der Tabelle zu löschen, wenn sie nicht mehr benötigt werden, kann die Tabelle wachsen, wenn die Anwendung vorzeitig beendet wird, und aus diesem Grund müssen Sie die Tabelle in einigen Fällen möglicherweise manuell löschen.

Behandeln von Commit-Fehlern mit früheren Versionen

Vor EF 6.1 gab es keinen Mechanismus zum Behandeln von Commit-Fehlern im EF-Produkt. Es gibt mehrere Möglichkeiten, mit dieser Situation umzugehen, die auf frühere Versionen von EF6 angewendet werden kann:

  • Option 1: Nichts tun

    Die Wahrscheinlichkeit eines Verbindungsfehlers während des Transaktionscommits ist niedrig, sodass es für Ihre Anwendung akzeptabel sein kann, nur fehlschlagen zu können, wenn diese Bedingung tatsächlich auftritt.

  • Option 2: Verwenden der Datenbank zum Zurücksetzen des Zustands

    1. Verwerfen des aktuellen DbContext
    2. Erstellen Sie einen neuen DbContext, und stellen Sie den Status Ihrer Anwendung aus der Datenbank wieder her
    3. Informieren Sie den Benutzer, dass der letzte Vorgang möglicherweise nicht erfolgreich abgeschlossen wurde
  • Option 3: Manuelles Nachverfolgen der Transaktion

    1. Fügen Sie der Datenbank eine nicht nachverfolgte Tabelle hinzu, die zum Nachverfolgen des Status der Transaktionen verwendet wird.
    2. Fügen Sie am Anfang jeder Transaktion eine Zeile in die Tabelle ein.
    3. Wenn die Verbindung während des Commits fehlschlägt, überprüfen Sie, ob die entsprechende Zeile in der Datenbank vorhanden ist.
      • Wenn die Zeile vorhanden ist, fahren Sie normal fort, da die Transaktion erfolgreich commitet wurde
      • Wenn die Zeile nicht vorhanden ist, verwenden Sie eine Ausführungsstrategie, um den aktuellen Vorgang erneut zu versuchen.
    4. Wenn der Commit erfolgreich ist, löschen Sie die entsprechende Zeile, um das Wachstum der Tabelle zu vermeiden.

Dieser Blogbeitrag enthält Beispielcode zum Ausführen dieser Vorgehensweise in SQL Azure.