Delen via


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 TRANSACTIONuitvoeren.

  • 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 TRANSACTIONuitvoeren.

  • 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

  1. Registreer de assembly.

    CREATE ASSEMBLY TestProcs
        FROM 'C:\Programming\TestProcs.dll';
    GO
    
    CREATE PROCEDURE uspRollbackFromProc
    AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc;
    GO
    
  2. 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
    
  3. Uw omgeving opschonen.

    DROP PROCEDURE uspRollbackFromProc;
    GO
    
    DROP ASSEMBLY TestProcs;
    GO