Wird eine using-Anweisung eine Datenbanktransaktion zurücksetzen, wenn ein Fehler auftritt?

82

Ich habe eine IDbTransaction in einer using-Anweisung, bin mir jedoch nicht sicher, ob sie zurückgesetzt wird, wenn in einer using-Anweisung eine Ausnahme ausgelöst wird. Ich weiß, dass eine using-Anweisung den Aufruf von Dispose () erzwingt ... aber weiß jemand, ob dies auch für Rollback () gilt?

Update: Muss ich Commit () auch explizit aufrufen, wie unten beschrieben, oder wird dies auch durch die using-Anweisung erledigt?

Mein Code sieht ungefähr so ​​aus:

using Microsoft.Practices.EnterpriseLibrary.Data;

...

using(IDbConnection connection = DatabaseInstance.CreateConnection())
{
    connection.Open();

    using(IDbTransaction transaction = connection.BeginTransaction())
    {
       //Attempt to do stuff in the database
       //potentially throw an exception
       transaction.Commit();
    }
}
Mezoid
quelle
3
Hallo, nur um den "Commit" -Fall zu klären. Dies ist natürlich obligatorisch, da using () {} einfach die Dispose () -Methode aufruft. Die Transaction.Dispose-Klasse konnte nicht wissen, ob sie festschreiben oder entsorgen sollte, wenn die
Festschreibung

Antworten:

104

Die Dispose-Methode für die Transaktionsklasse führt ein Rollback durch, während die Oracle-Klasse dies nicht tut. Aus Sicht der Transaktion ist die Implementierung also abhängig.

Die usingAnweisung für das Verbindungsobjekt würde andererseits entweder die Verbindung zur Datenbank schließen oder die Verbindung nach dem Zurücksetzen an den Pool zurückgeben. In beiden Fällen sollten die ausstehenden Transaktionen zurückgesetzt werden. Aus diesem Grund lässt eine Ausnahme niemals eine aktive Transaktion herumliegen.

Ja, Sie sollten auch Commit()explizit anrufen .

Sedat Kapanoglu
quelle
Ich werde dies sogar einmal testen, indem ich explizit eine Ausnahme auslöste.
Pawel Krakowiak
1
Das ist großartig, aber funktioniert es für andere Implementierungen von IDbTransaction, wenn Sie es aus Gründen der Cross-DB-Kompatibilität verwenden?
Matt Hamilton
4
@mezoid: Commit wird niemals automatisch stattfinden. @ Matt: Sie sollten von Natur aus.
Sedat Kapanoglu
1
@ MattHamilton genau wie ssg sagte. Ich habe die .net-Connector-Quelle von MySQL überprüft. Sie haben das Gleiche wie oben gezeigt. Rollbackwird gerufen Dispose! :)
Nawfal
1
Wenn Sie ein verwenden System.Data.OracleConnection, wird es bei der Entsorgung nicht zurückgesetzt. Zumindest für uns nicht.
Medinoc
20

Sie müssen Commit aufrufen. Die using-Anweisung legt nichts für Sie fest.

jhale
quelle
5
Ja, die Verwendung ruft Dispose beim Beenden auf, wodurch Rollback und nicht Commit aufgerufen wird.
Ehrfurcht
4

Ich glaube, wenn es eine Ausnahme gibt, Commit()die nie aufgerufen wurde, wird die Transaktion automatisch zurückgesetzt.

Tommy Hui
quelle
Ja das ist mein Verständnis. Eine Transaktion läuft so lange, bis ein Commit aufgerufen wird oder die Verbindung beendet wird. Zu diesem Zeitpunkt wird das Transaktionsprotokoll tatsächlich mit den Änderungen aktualisiert oder im Falle einer geschlossenen Verbindung zurückgesetzt (Sie wissen, dass Sie bei einer geschlossenen Verbindung niemals ein Commit erhalten;)).
Mike