Sdílet prostřednictvím


Přístup k aktuální transakci

platí pro:SQL Server

Pokud je transakce aktivní v okamžiku, kdy je zadán kód CLR (Common Language Runtime) spuštěný na SQL Serveru, transakce je vystavena prostřednictvím System.Transactions.Transaction třídy. Vlastnost Transaction.Current slouží k přístupu k aktuální transakci. Ve většině případů není nutné explicitně přistupovat k transakci. U databázových připojení ADO.NET kontroluje Transaction.Current automaticky, když je volána metoda Connection.Open, a transparentně začte připojení v této transakci (pokud není klíčové slovo Enlist nastaveno na false v připojovacím řetězci).

Objekt Transaction můžete chtít použít přímo v následujících scénářích:

  • Pokud chcete přidat prostředek, který neprovádí automatické zařazení, nebo z nějakého důvodu nebyl zařazen během inicializace.

  • Pokud chcete explicitně přidat prostředek do transakce.

  • Chcete-li ukončit externí transakce z uložené procedury nebo funkce. V tomto případě použijete TransactionScope. Například následující kód vrátí zpět aktuální transakci:

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

Zbytek tohoto článku popisuje další způsoby zrušení externí transakce.

Zrušení externí transakce

Externí transakce můžete ze spravované procedury nebo funkce zrušit následujícími způsoby:

  • Spravovaná procedura nebo funkce může vrátit hodnotu pomocí výstupního parametru. Volající Transact-SQL procedura může zkontrolovat vrácenou hodnotu a v případě potřeby provést ROLLBACK TRANSACTION.

  • Spravovaná procedura nebo funkce může vyvolat vlastní výjimku. Volání Transact-SQL procedura může zachytit výjimku vyvolanou spravovanou procedurou nebo funkcí v bloku try/catch a spustit ROLLBACK TRANSACTION.

  • Spravovaná procedura nebo funkce může zrušit aktuální transakci voláním Transaction.Rollback metody, pokud je splněna určitá podmínka.

Pokud je metoda Transaction.Rollback volána v rámci spravované procedury nebo funkce, vyvolá výjimku s nejednoznačným chybovou zprávou a může být zabalena do bloku try/catch. Chybová zpráva se podobá následujícímu výstupu:

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.

Tato výjimka je očekávaná a blok try/catch je nezbytný pro pokračování provádění kódu. Bez bloku try/catch je výjimka okamžitě vyvolán voláním Transact-SQL procedura a provádění spravovaného kódu se dokončí. Po dokončení provádění spravovaného kódu se vyvolá další výjimka:

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.

Tato výjimka je také očekávaná a aby bylo možné pokračovat spuštěním, musíte mít blok try/catch kolem příkazu Transact-SQL, který provede akci, která aktivuje trigger. Navzdory dvěma vyvolaných výjimkám se transakce vrátí zpět a změny nejsou potvrzeny.

Příklad

Následující kód je příkladem transakce, která se vrací ze spravované procedury pomocí Transaction.Rollback metody. Všimněte si bloku try/catch kolem metody Transaction.Rollback ve spravovaném kódu. Skript Transact-SQL vytvoří sestavení a spravovanou uloženou proceduru. Příkaz EXEC uspRollbackFromProc je zabalený do bloku try/catch, aby se výjimka vyvolaná při dokončení provádění spravované procedury.

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

Registrace a spuštění sestavení v Transact-SQL

  1. Zaregistrujte sestavení.

    CREATE ASSEMBLY TestProcs
        FROM 'C:\Programming\TestProcs.dll';
    GO
    
    CREATE PROCEDURE uspRollbackFromProc
    AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc;
    GO
    
  2. Spusťte proceduru.

    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. Vyčistěte prostředí.

    DROP PROCEDURE uspRollbackFromProc;
    GO
    
    DROP ASSEMBLY TestProcs;
    GO