Accéder à la transaction actuelle
S'applique à :SQL Server
Si une transaction est active au point où le code CLR (Common Language Runtime) exécuté sur SQL Server est entré, la transaction est exposée via la classe System.Transactions.Transaction
. La propriété Transaction.Current
est utilisée pour accéder à la transaction actuelle. Dans la plupart des cas, il n’est pas nécessaire d’accéder explicitement à la transaction. Pour les connexions de base de données, ADO.NET vérifie Transaction.Current
automatiquement lorsque la méthode Connection.Open
est appelée et inscrit de manière transparente la connexion dans cette transaction (sauf si le mot clé Enlist
a la valeur false dans la chaîne de connexion).
Vous pouvez utiliser l’objet Transaction
directement dans les scénarios suivants :
Si vous souhaitez inscrire une ressource qui ne fait pas d’inscription automatique, ou que, pour une raison quelconque, n’a pas été inscrite pendant l’initialisation.
Si vous souhaitez inscrire explicitement une ressource dans la transaction.
Si vous souhaitez mettre fin à la transaction externe à partir de votre procédure stockée ou fonction. Dans ce cas, vous utilisez TransactionScope. Par exemple, le code suivant restaure la transaction actuelle :
using(TransactionScope transactionScope = new TransactionScope(TransactionScopeOptions.Required)) { }
Le reste de cet article décrit d’autres façons d’annuler une transaction externe.
Annuler une transaction externe
Vous pouvez annuler des transactions externes à partir d'une procédure ou fonction managée des manières suivantes :
La procédure ou fonction managée peut renvoyer une valeur en utilisant un paramètre de sortie. La procédure Transact-SQL appelante peut vérifier la valeur retournée et, le cas échéant, exécuter
ROLLBACK TRANSACTION
.La procédure ou fonction managée peut lever une exception personnalisée. La procédure Transact-SQL appelante peut intercepter l’exception levée par la procédure managée ou la fonction dans un bloc try/catch et exécuter
ROLLBACK TRANSACTION
.La procédure managée ou la fonction peut annuler la transaction actuelle en appelant la méthode
Transaction.Rollback
si une certaine condition est remplie.
Lorsque la méthode Transaction.Rollback
est appelée dans une procédure ou une fonction managée, elle lève une exception avec un message d’erreur ambigu et peut être encapsulée dans un bloc try/catch. Le message d’erreur est similaire à la sortie suivante :
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.
Cette exception est attendue et le bloc try/catch est nécessaire pour que l'exécution du code continue. Sans le bloc try/catch, l’exception est immédiatement levée à la procédure d’appel Transact-SQL et l’exécution du code managé se termine. Lorsque l'exécution du code managé se termine, une autre exception est levée :
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.
Cette exception est également attendue et, pour l’exécution, vous devez disposer d’un bloc try/catch autour de l’instruction Transact-SQL qui effectue l’action qui déclenche le déclencheur. Malgré les deux exceptions levées, la transaction est restaurée et les modifications ne sont pas validées.
Exemple
Le code suivant est un exemple de restauration d’une transaction à partir d’une procédure managée à l’aide de la méthode Transaction.Rollback
. Notez le bloc try/catch autour de la méthode Transaction.Rollback
dans le code managé. Le script Transact-SQL crée un assembly et une procédure stockée managée. L’instruction EXEC uspRollbackFromProc
est encapsulée dans un bloc try/catch, afin que l’exception levée lorsque la procédure managée termine l’exécution est interceptée.
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();
}
}
};
Inscrire et exécuter l’assembly dans Transact-SQL
Inscrivez l’assembly.
CREATE ASSEMBLY TestProcs FROM 'C:\Programming\TestProcs.dll'; GO CREATE PROCEDURE uspRollbackFromProc AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc; GO
Exécutez la procédure.
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
Nettoyez votre environnement.
DROP PROCEDURE uspRollbackFromProc; GO DROP ASSEMBLY TestProcs; GO