Udostępnij przez


Uzyskiwanie dostępu do bieżącej transakcji

Dotyczy:programu SQL Server

Jeśli transakcja jest aktywna w momencie, w którym wprowadzono kod środowiska uruchomieniowego języka wspólnego (CLR) uruchomiony w programie SQL Server, transakcja jest uwidoczniona za pośrednictwem klasy System.Transactions.Transaction. Właściwość Transaction.Current służy do uzyskiwania dostępu do bieżącej transakcji. W większości przypadków nie jest konieczne jawne uzyskanie dostępu do transakcji. W przypadku połączeń z bazą danych ADO.NET sprawdza, Transaction.Current automatycznie, gdy wywoływana jest metoda Connection.Open, i w sposób niewidoczny powoduje zarejestrowanie połączenia w tej transakcji (chyba że słowo kluczowe Enlist ma wartość false w parametrach połączenia).

Możesz chcieć użyć obiektu Transaction bezpośrednio w następujących scenariuszach:

  • Jeśli chcesz zarejestrować zasób, który nie wykonuje automatycznej rejestracji lub z jakiegoś powodu nie został wymieniony podczas inicjowania.

  • Jeśli chcesz jawnie zarejestrować zasób w transakcji.

  • Jeśli chcesz zakończyć transakcję zewnętrzną z poziomu procedury składowanej lub funkcji. W tym przypadku użyjesz TransactionScope. Na przykład następujący kod cofa bieżącą transakcję:

    using(TransactionScope transactionScope = new TransactionScope(TransactionScopeOptions.Required)) { }
    

W pozostałej części tego artykułu opisano inne sposoby anulowania transakcji zewnętrznej.

Anulowanie transakcji zewnętrznej

Transakcje zewnętrzne można anulować z poziomu procedury zarządzanej lub funkcji w następujący sposób:

  • Procedura zarządzana lub funkcja może zwrócić wartość przy użyciu parametru wyjściowego. Procedura wywoływania Transact-SQL może sprawdzić zwróconą wartość i, jeśli jest to konieczne, wykonać ROLLBACK TRANSACTION.

  • Procedura zarządzana lub funkcja może zgłaszać wyjątek niestandardowy. Procedura wywoływania Transact-SQL może przechwycić wyjątek zgłoszony przez procedurę zarządzaną lub funkcję w bloku try/catch i wykonać ROLLBACK TRANSACTION.

  • Procedura zarządzana lub funkcja może anulować bieżącą transakcję, wywołując metodę Transaction.Rollback, jeśli zostanie spełniony określony warunek.

Gdy metoda Transaction.Rollback jest wywoływana w ramach zarządzanej procedury lub funkcji, zgłasza wyjątek z niejednoznacznym komunikatem o błędzie i może zostać opakowany w bloku try/catch. Komunikat o błędzie jest podobny do następujących danych wyjściowych:

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.

Ten wyjątek jest oczekiwany, a blok try/catch jest niezbędny do kontynuowania wykonywania kodu. Bez bloku try/catch wyjątek jest natychmiast zgłaszany do procedury wywoływania Transact-SQL i kończy wykonywanie kodu zarządzanego. Po zakończeniu wykonywania kodu zarządzanego zostanie zgłoszony inny wyjątek:

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.

Ten wyjątek jest również oczekiwany, a wykonanie w celu kontynuowania musi mieć blok try/catch wokół instrukcji Transact-SQL, która wykonuje akcję uruchamiającą wyzwalacz. Pomimo zgłoszonych dwóch wyjątków transakcja jest cofana, a zmiany nie są zatwierdzane.

Przykład

Poniższy kod to przykład transakcji wycofanej z procedury zarządzanej przy użyciu metody Transaction.Rollback. Zwróć uwagę na blok try/catch wokół metody Transaction.Rollback w kodzie zarządzanym. Skrypt Transact-SQL tworzy zestaw i zarządzaną procedurę składowaną. Instrukcja EXEC uspRollbackFromProc jest owinięta w bloku try/catch, tak aby wyjątek zgłaszany podczas wykonywania procedury zarządzanej został przechwycony.

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();
   }
}
};

Rejestrowanie i wykonywanie zestawu w Transact-SQL

  1. Zarejestruj zestaw.

    CREATE ASSEMBLY TestProcs
        FROM 'C:\Programming\TestProcs.dll';
    GO
    
    CREATE PROCEDURE uspRollbackFromProc
    AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc;
    GO
    
  2. Uruchom procedurę.

    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. Czyszczenie środowiska.

    DROP PROCEDURE uspRollbackFromProc;
    GO
    
    DROP ASSEMBLY TestProcs;
    GO