共用方式為


存取目前的交易

適用於:SQL Server

如果交易在 SQL Server 上執行的 Common Language Runtime (CLR) 程式代碼進入作用中時,交易會透過 System.Transactions.Transaction 類別公開。 Transaction.Current 屬性可用來存取目前的交易。 在大部分情況下,不需要明確存取交易。 針對資料庫連接,ADO.NET 會在呼叫 Connection.Open 方法時自動檢查 Transaction.Current,並透明地登記該交易中的連接(除非連接字串中的 Enlist 關鍵詞設定為 false)。

您可能想要在下列案例中直接使用 Transaction 物件:

  • 如果您想要登記未自動登記的資源,或基於某些原因未在初始化期間登記。

  • 如果您想要在交易中明確登記資源。

  • 如果您想要從預存程式或函式內終止外部交易。 在這裡情況下,您會使用 TransactionScope。 例如,下列程式代碼會回復目前的交易:

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

本文的其餘部分說明其他取消外部交易的方式。

取消外部交易

您可以透過下列方式,從 Managed 程式或函式取消外部交易:

  • Managed 程式或函式可以使用輸出參數傳回值。 呼叫 Transact-SQL 程式可以檢查傳回的值,如果適當的話,請執行 ROLLBACK TRANSACTION

  • Managed 程式或函式可以擲回自定義例外狀況。 呼叫 Transact-SQL 程式可以攔截 managed 程式或函式在 try/catch 區塊中擲回的例外狀況,並執行 ROLLBACK TRANSACTION

  • 如果符合特定條件,Managed 程式或函式可以藉由呼叫 Transaction.Rollback 方法來取消目前的交易。

在 Managed 程式或函式內呼叫 Transaction.Rollback 方法時,它會擲回具有模棱兩可錯誤訊息的例外狀況,而且可以包裝在 try/catch 區塊中。 錯誤訊息類似於下列輸出:

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.

這是預期的例外狀況,而且需要 try/catch 區塊,程式代碼執行才能繼續。 如果沒有 try/catch 區塊,就會立即將例外狀況擲回呼叫 Transact-SQL 程式和 Managed 程式代碼執行完成。 當 Managed 程式代碼完成執行時,會引發另一個例外狀況:

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.

此例外狀況也是預期的,而且若要繼續執行,您必須在 Transact-SQL 語句周圍有 try/catch 區塊,以執行引發觸發程式的動作。 儘管擲回了兩個例外狀況,但交易仍會回復,且不會認可變更。

範例

下列程式代碼是使用 Transaction.Rollback 方法,從 Managed 程式復原的交易範例。 請注意managed程式代碼中 Transaction.Rollback 方法周圍的 try/catch 區塊。 Transact-SQL 腳本會建立元件和受控預存程式。 EXEC uspRollbackFromProc 語句會包裝在 try/catch 區塊中,讓 Managed 程式完成執行時擲回的例外狀況。

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

在 Transact-SQL 中註冊和執行元件

  1. 註冊元件。

    CREATE ASSEMBLY TestProcs
        FROM 'C:\Programming\TestProcs.dll';
    GO
    
    CREATE PROCEDURE uspRollbackFromProc
    AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc;
    GO
    
  2. 執行程式。

    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. 清除您的環境。

    DROP PROCEDURE uspRollbackFromProc;
    GO
    
    DROP ASSEMBLY TestProcs;
    GO