Toegang tot de huidige transactie
van toepassing op:SQL Server-
Als een transactie actief is op het punt waarop CLR-code (Common Language Runtime) wordt ingevoerd die wordt uitgevoerd op SQL Server, wordt de transactie weergegeven via de System.Transactions.Transaction
-klasse. De eigenschap Transaction.Current
wordt gebruikt voor toegang tot de huidige transactie. In de meeste gevallen is het niet nodig om expliciet toegang te krijgen tot de transactie. Voor databaseverbindingen controleert ADO.NET automatisch Transaction.Current
wanneer de methode Connection.Open
wordt aangeroepen en wordt de verbinding in die transactie transparant opgenomen (tenzij het trefwoord Enlist
is ingesteld op onwaar in de verbindingsreeks).
U kunt het Transaction
-object rechtstreeks in de volgende scenario's gebruiken:
Als u een resource wilt opnemen die geen automatische opname uitvoert of die om een of andere reden niet is ingeschreven tijdens de initialisatie.
Als u expliciet een resource in de transactie wilt opnemen.
Als u de externe transactie wilt beƫindigen vanuit uw opgeslagen procedure of functie. In dit geval gebruikt u TransactionScope. Met de volgende code wordt bijvoorbeeld de huidige transactie teruggedraaid:
using(TransactionScope transactionScope = new TransactionScope(TransactionScopeOptions.Required)) { }
In de rest van dit artikel worden andere manieren beschreven om een externe transactie te annuleren.
Een externe transactie annuleren
U kunt externe transacties op de volgende manieren annuleren vanuit een beheerde procedure of functie:
De beheerde procedure of functie kan een waarde retourneren met behulp van een uitvoerparameter. De aanroepende Transact-SQL procedure kan de geretourneerde waarde controleren en, indien van toepassing,
ROLLBACK TRANSACTION
uitvoeren.Met de beheerde procedure of functie kan een aangepaste uitzondering worden gegenereerd. De aanroepende Transact-SQL procedure kan de uitzondering ondervangen die is gegenereerd door de beheerde procedure of functie in een try/catch-blok en
ROLLBACK TRANSACTION
uitvoeren.De beheerde procedure of functie kan de huidige transactie annuleren door de
Transaction.Rollback
methode aan te roepen als aan een bepaalde voorwaarde wordt voldaan.
Wanneer de methode Transaction.Rollback
wordt aangeroepen binnen een beheerde procedure of functie, genereert deze een uitzondering met een dubbelzinnig foutbericht en kan deze worden verpakt in een try/catch-blok. Het foutbericht is vergelijkbaar met de volgende uitvoer:
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.
Deze uitzondering wordt verwacht en het try/catch-blok is nodig voor het uitvoeren van code om door te gaan. Zonder het try/catch-blok wordt de uitzondering onmiddellijk gegenereerd voor de aanroepende Transact-SQL procedure en de uitvoering van beheerde code is voltooid. Wanneer de uitvoering van de beheerde code is voltooid, wordt er een andere uitzondering gegenereerd:
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.
Deze uitzondering wordt ook verwacht en voor uitvoering moet u een try/catch-blok hebben rond de Transact-SQL-instructie waarmee de actie wordt uitgevoerd waarmee de trigger wordt geactiveerd. Ondanks de twee uitzonderingen die zijn opgetreden, wordt de transactie teruggedraaid en worden de wijzigingen niet doorgevoerd.
Voorbeeld
De volgende code is een voorbeeld van een transactie die wordt teruggedraaid vanuit een beheerde procedure met behulp van de methode Transaction.Rollback
. Let op het try/catch-blok rond de methode Transaction.Rollback
in de beheerde code. Het Transact-SQL-script maakt een assembly en beheerde opgeslagen procedure. De EXEC uspRollbackFromProc
instructie wordt verpakt in een try/catch-blok, zodat de uitzondering die optreedt wanneer de beheerde procedure de uitvoering voltooit, wordt afgevangen.
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();
}
}
};
De assembly registreren en uitvoeren in Transact-SQL
Registreer de assembly.
CREATE ASSEMBLY TestProcs FROM 'C:\Programming\TestProcs.dll'; GO CREATE PROCEDURE uspRollbackFromProc AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc; GO
Voer de procedure uit.
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
Uw omgeving opschonen.
DROP PROCEDURE uspRollbackFromProc; GO DROP ASSEMBLY TestProcs; GO