共用方式為


存取目前交易

適用於: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();  
   }  
}  
};  
Imports System  
Imports System.Data  
Imports System.Data.SqlClient  
Imports System.Data.SqlTypes  
Imports Microsoft.SqlServer.Server  
Imports System.Transactions  
  
Partial Public Class StoredProcedures  
<Microsoft.SqlServer.Server.SqlProcedure()> _  
Public Shared Sub  uspRollbackFromProc ()  
   Using connection As New SqlConnection("context connection=true")  
  
   ' Open the connection.  
   connection.Open()  
  
   Dim successCondition As Boolean  
   successCondition = False  
  
   ' Success condition is met.  
   If successCondition Then  
  
      SqlContext.Pipe.Send("Success condition met in procedure.")  
  
      ' 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.  
         Dim trans As Transaction  
         trans = Transaction.Current  
         trans.Rollback()  
  
      Catch ex As SqlException  
         ' Catch the exception instead of throwing it.    
         ' This allows the connection to close correctly.                      
      End Try  
  
   End If  
  
   ' Close the connection.  
   connection.Close()  
  
End Using  
End Sub  
End Class  

Transact-SQL

--Register assembly.  
CREATE ASSEMBLY TestProcs FROM 'C:\Programming\TestProcs.dll'   
Go  
CREATE PROCEDURE uspRollbackFromProc AS EXTERNAL NAME TestProcs.StoredProcedures.uspRollbackFromProc  
Go  
  
-- Execute procedure.  
BEGIN TRY  
BEGIN TRANSACTION   
-- Perform other actions.  
Exec 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 TRANSACTION  
PRINT N'Transaction rolled back.'   
END CATCH  
Go  
  
-- Clean up.  
DROP Procedure uspRollbackFromProc;  
Go  
DROP ASSEMBLY TestProcs;  
Go  

另請參閱

CLR 整合和交易