Zugreifen auf die aktuelle Transaktion
Gilt für:SQL Server
Wenn eine Transaktion an dem Punkt aktiv ist, an dem clR-Code (Common Language Runtime), der auf SQL Server ausgeführt wird, eingegeben wird, wird die Transaktion über die System.Transactions.Transaction
-Klasse verfügbar gemacht. Die Transaction.Current
-Eigenschaft wird für den Zugriff auf die aktuelle Transaktion verwendet. In den meisten Fällen ist es nicht erforderlich, explizit auf die Transaktion zuzugreifen. Bei Datenbankverbindungen überprüft ADO.NET Transaction.Current
automatisch, wenn die Connection.Open
Methode aufgerufen wird, und führt die Verbindung in dieser Transaktion transparent auf (es sei denn, das schlüsselwort Enlist
ist in der Verbindungszeichenfolge auf "false" festgelegt).
Möglicherweise möchten Sie das Transaction
-Objekt direkt in den folgenden Szenarien verwenden:
Wenn Sie eine Ressource auflisten möchten, die keine automatische Listenliste vorgibt oder die aus irgendeinem Grund während der Initialisierung nicht aufgelistet wurde.
Wenn Sie eine Ressource explizit in die Transaktion eintragen möchten.
Wenn Sie die externe Transaktion aus einer gespeicherten Prozedur oder Funktion heraus beenden möchten. In diesem Fall verwenden Sie TransactionScope. Der folgende Code setzt z. B. die aktuelle Transaktion zurück:
using(TransactionScope transactionScope = new TransactionScope(TransactionScopeOptions.Required)) { }
Im restlichen Artikel werden weitere Möglichkeiten zum Abbrechen einer externen Transaktion beschrieben.
Abbrechen einer externen Transaktion
Sie können externe Transaktionen wie folgt von einer verwalteten Prozedur oder einer Funktion aus abbrechen:
Die verwaltete Prozedur oder die Funktion kann in einem Ausgabeparameter einen Wert zurückgeben. Die aufrufende Transact-SQL Prozedur kann den zurückgegebenen Wert überprüfen und ggf.
ROLLBACK TRANSACTION
ausführen.Die verwaltete Prozedur oder die Funktion kann eine benutzerdefinierte Ausnahme auslösen. Die aufrufende Transact-SQL-Prozedur kann die Ausnahme abfangen, die von der verwalteten Prozedur oder Funktion in einem Try/Catch-Block ausgelöst und
ROLLBACK TRANSACTION
ausgeführt wird.Die verwaltete Prozedur oder Funktion kann die aktuelle Transaktion abbrechen, indem sie die
Transaction.Rollback
Methode aufruft, wenn eine bestimmte Bedingung erfüllt ist.
Wenn die Transaction.Rollback
-Methode in einer verwalteten Prozedur oder Funktion aufgerufen wird, löst sie eine Ausnahme mit einer mehrdeutigen Fehlermeldung aus und kann in einen Try/Catch-Block eingeschlossen werden. Die Fehlermeldung ähnelt der folgenden Ausgabe:
Msg 3994, Level 16, State 1, Procedure uspRollbackFromProc, Line 0
Transaction is not allowed to roll back inside a user defined routine, trigger or aggregate because the transaction is not started in that CLR level. Change application logic to enforce strict transaction nesting.
Diese Ausnahme wird erwartet und der try/catch-Block ist notwendig, damit die Codeausführung fortgesetzt wird. Ohne den Try/Catch-Block wird die Ausnahme sofort an die aufrufende Transact-SQL Prozedur ausgelöst, und die Ausführung von verwaltetem Code wird beendet. Wenn die Ausführung des verwalteten Codes beendet ist, wird eine andere Ausnahme ausgelöst.
Msg 3991, Level 16, State 1, Procedure uspRollbackFromProc, Line 1
The context transaction which was active before entering user defined routine, trigger or aggregate " uspRollbackFromProc " has been ended inside of it, which is not allowed. Change application logic to enforce strict transaction nesting. The statement has been terminated.
Diese Ausnahme wird ebenfalls erwartet, und damit die Ausführung fortgesetzt wird, benötigen Sie einen Try/Catch-Block um die Transact-SQL-Anweisung, die die Aktion ausführt, die den Trigger auslöst. Trotz der beiden ausgelösten Ausnahmen wird die Transaktion zurückgesetzt, und die Änderungen werden nicht übernommen.
Beispiel
Der folgende Code ist ein Beispiel für eine Transaktion, die mithilfe der Transaction.Rollback
-Methode aus einer verwalteten Prozedur zurückgesetzt wird. Beachten Sie den Try/Catch-Block um die Transaction.Rollback
-Methode im verwalteten Code. Das Transact-SQL-Skript erstellt eine Assembly- und verwaltete gespeicherte Prozedur. Die EXEC uspRollbackFromProc
-Anweisung wird in einen Try/Catch-Block eingeschlossen, sodass die Ausnahme ausgelöst wird, wenn die verwaltete Prozedur die Ausführung abgeschlossen hat.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Transactions;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void uspRollbackFromProc()
{
using (SqlConnection connection = new SqlConnection(@"context connection=true"))
{
// Open the connection.
connection.Open();
bool successCondition = true;
// Success condition is met.
if (successCondition)
{
SqlContext.Pipe.Send("Success condition met in procedure.");
// Perform other actions here.
}
// Success condition is not met, the transaction will be rolled back.
else
{
SqlContext.Pipe.Send("Success condition not met in managed procedure. Transaction rolling back...");
try
{
// Get the current transaction and roll it back.
Transaction trans = Transaction.Current;
trans.Rollback();
}
catch (SqlException ex)
{
// Catch the expected exception.
// This allows the connection to close correctly.
}
}
// Close the connection.
connection.Close();
}
}
};
Registrieren und Ausführen der Assembly in Transact-SQL
Registrieren Sie die Assembly.
CREATE ASSEMBLY TestProcs FROM 'C:\Programming\TestProcs.dll'; GO CREATE PROCEDURE uspRollbackFromProc AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc; GO
Führen Sie die Prozedur aus.
BEGIN TRY BEGIN TRANSACTION; -- Perform other actions. EXECUTE uspRollbackFromProc; -- Perform other actions. PRINT N'Commiting transaction...'; COMMIT TRANSACTION; END TRY BEGIN CATCH SELECT ERROR_NUMBER() AS ErrorNum, ERROR_MESSAGE() AS ErrorMessage; PRINT N'Exception thrown, rolling back transaction.'; ROLLBACK; PRINT N'Transaction rolled back.'; END CATCH GO
Bereinigen Sie Ihre Umgebung.
DROP PROCEDURE uspRollbackFromProc; GO DROP ASSEMBLY TestProcs; GO