.net中的分佈式事務

NET Framework 類庫

TransactionScope 類
注意:此類在 .NET Framework 2.0 版中是新增的。

使代碼塊成爲事務性代碼。無法繼承此類。

命名空間:System.Transactions
程序集:System.Transactions(在 system.transactions.dll 中)

 語法
Visual Basic(聲明)
Public NotInheritable Class TransactionScope
    Implements IDisposable
 
Visual Basic(用法)
Dim instance As TransactionScope
 
C#
public sealed class TransactionScope : IDisposable
 
C++
public ref class TransactionScope sealed : IDisposable
 
J#
public final class TransactionScope implements IDisposable
 
JScript
public final class TransactionScope implements IDisposable
 

 備註
System.Transactions 基礎結構既提供了基於 Transaction 類的顯式編程模型,也提供了使用 TransactionScope 類的隱式編程模型,在後一種模型中,事務由該基礎結構自動管理。

重要事項:
建議使用 TransactionScope 類創建隱式事務,以便自動爲您管理環境事務上下文。對於需要跨多個函數調用或多個線程調用使用相同事務的應用程序,您還應該使用 TransactionScope 和 DependentTransaction 類。有關此模型的更多信息,請參見 使用事務範圍實現隱式事務 主題。有關編寫事務性應用程序的更多信息,請參見 編寫事務性應用程序。
 


在通過 new 語句實例化 TransactionScope 時,事務管理器將確定要參與哪個事務。一經確定,此範圍將始終參與該事務。此決策基於兩個因素:是否存在環境事務以及構造函數中 TransactionScopeOption 參數的值。環境事務是在其中執行您的代碼的事務。通過調用 Transaction 類的 Current 靜態屬性可獲取對環境事務的引用。有關如何使用此參數的更多信息,請參見 使用事務範圍實現隱式事務 主題的“事務流管理”一節。

如果在事務範圍中(即從初始化 TransactionScope 對象到調用其 Dispose 方法之間)未發生異常,則允許該範圍所參與的事務繼續。如果事務範圍中的確發生了異常,它所參與的事務將回滾。

當應用程序完成它要在一個事務中執行的所有工作以後,您應當只調用 Complete 方法一次,以通知事務管理器可以接受提交事務。未能調用此方法將中止該事務。

對 Dispose 方法的調用標誌着該事務範圍的結束。在調用此方法之後發生的異常不會影響該事務。

如果在範圍中修改 Current 的值,則會在調用 Dispose 時引發異常。但是,在該範圍結束時,先前的值將被還原。此外,如果在創建事務的事務範圍內對 Current 調用 Dispose,則該事務將在相應範圍末尾處中止。

 示例
下面的示例演示如何使用 TransactionScope 類定義代碼塊以參與事務。


Visual Basic 複製代碼
'  This function takes arguments for 2 connection strings and commands to create a transaction
'  involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
'  transaction is rolled back. To test this code, you can connect to two different databases
'  on the same server by altering the connection string, or to another RDBMS such as Oracle
'  by altering the code in the connection2 code block.
Public Function CreateTransactionScope( _
  ByVal connectString1 As String, ByVal connectString2 As String, _
  ByVal commandText1 As String, ByVal commandText2 As String) As Integer

    ' Initialize the return value to zero and create a StringWriter to display results.
    Dim returnValue As Integer = 0
    Dim writer As System.IO.StringWriter = New System.IO.StringWriter

    ' Create the TransactionScope to execute the commands, guaranteeing
    '  that both commands can commit or roll back as a single unit of work.
    Using scope As New TransactionScope()
        Using connection1 As New SqlConnection(connectString1)
            Try
                ' Opening the connection automatically enlists it in the
                ' TransactionScope as a lightweight transaction.
                connection1.Open()

                ' Create the SqlCommand object and execute the first command.
                Dim command1 As SqlCommand = New SqlCommand(commandText1, connection1)
                returnValue = command1.ExecuteNonQuery()
                writer.WriteLine("Rows to be affected by command1: {0}", returnValue)

                ' If you get here, this means that command1 succeeded. By nesting
                ' the using block for connection2 inside that of connection1, you
                ' conserve server and network resources as connection2 is opened
                ' only when there is a chance that the transaction can commit.  
                 Using connection2 As New SqlConnection(connectString2)
                    Try
                        ' The transaction is escalated to a full distributed
                        ' transaction when connection2 is opened.
                        connection2.Open()

                        ' Execute the second command in the second database.
                        returnValue = 0
                        Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2)
                        returnValue = command2.ExecuteNonQuery()
                        writer.WriteLine("Rows to be affected by command2: {0}", returnValue)

                    Catch ex As Exception
                        ' Display information that command2 failed.
                        writer.WriteLine("returnValue for command2: {0}", returnValue)
                        writer.WriteLine("Exception Message2: {0}", ex.Message)
                    End Try
                End Using

            Catch ex As Exception
                ' Display information that command1 failed.
                writer.WriteLine("returnValue for command1: {0}", returnValue)
                writer.WriteLine("Exception Message1: {0}", ex.Message)
            End Try
        End Using

        ' The Complete method commits the transaction. If an exception has been thrown,
        ' Complete is called and the transaction is rolled back.
        scope.Complete()
    End Using

    ' The returnValue is greater than 0 if the transaction committed.
    If returnValue > 0 Then
        writer.WriteLine("Transaction was committed.")
    Else
       ' You could write additional business logic here, for example, you can notify the caller
       ' by throwing a TransactionAbortedException, or logging the failure.
       writer.WriteLine("Transaction rolled back.")
     End If

    ' Display messages.
    Console.WriteLine(writer.ToString())

    Return returnValue
End Function
 
C# 複製代碼
// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another RDBMS such as Oracle
// by altering the code in the connection2 code block.
static public int CreateTransactionScope(
    string connectString1, string connectString2,
    string commandText1, string commandText2)
{
    // Initialize the return value to zero and create a StringWriter to display results.
    int returnValue = 0;
    System.IO.StringWriter writer = new System.IO.StringWriter();

    // Create the TransactionScope to execute the commands, guaranteeing
    // that both commands can commit or roll back as a single unit of work.
    using (TransactionScope scope = new TransactionScope())
    {
        using (SqlConnection connection1 = new SqlConnection(connectString1))
        {
            try
            {
                // Opening the connection automatically enlists it in the
                // TransactionScope as a lightweight transaction.
                connection1.Open();

                // Create the SqlCommand object and execute the first command.
                SqlCommand command1 = new SqlCommand(commandText1, connection1);
                returnValue = command1.ExecuteNonQuery();
                writer.WriteLine("Rows to be affected by command1: {0}", returnValue);

                // If you get here, this means that command1 succeeded. By nesting
                // the using block for connection2 inside that of connection1, you
                // conserve server and network resources as connection2 is opened
                // only when there is a chance that the transaction can commit.  
                using (SqlConnection connection2 = new SqlConnection(connectString2))
                    try
                    {
                        // The transaction is escalated to a full distributed
                        // transaction when connection2 is opened.
                        connection2.Open();

                        // Execute the second command in the second database.
                        returnValue = 0;
                        SqlCommand command2 = new SqlCommand(commandText2, connection2);
                        returnValue = command2.ExecuteNonQuery();
                        writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
                    }
                    catch (Exception ex)
                    {
                        // Display information that command2 failed.
                        writer.WriteLine("returnValue for command2: {0}", returnValue);
                        writer.WriteLine("Exception Message2: {0}", ex.Message);
                    }
            }
            catch (Exception ex)
            {
                // Display information that command1 failed.
                writer.WriteLine("returnValue for command1: {0}", returnValue);
                writer.WriteLine("Exception Message1: {0}", ex.Message);
            }
        }

        // The Complete method commits the transaction. If an exception has been thrown,
        // Complete is not  called and the transaction is rolled back.
        scope.Complete();
    }

    // The returnValue is greater than 0 if the transaction committed.
    if (returnValue > 0)
    {
        writer.WriteLine("Transaction was committed.");
    }
    else
    {
        // You could write additional business logic here, for example, you can notify the caller
        // by throwing a TransactionAbortedException, or logging the failure.
        writer.WriteLine("Transaction rolled back.");
    }

    // Display messages.
    Console.WriteLine(writer.ToString());

    return returnValue;
}
 

 繼承層次結構
System.Object
  System.Transactions.TransactionScope

 線程安全
該類型對於多線程操作是安全的。

 平臺
Windows 98、Windows 2000 SP4、Windows Millennium Edition、Windows Server 2003、Windows XP Media Center Edition、Windows XP Professional x64 Edition、Windows XP SP2、Windows XP Starter Edition

.NET Framework 並不是對每個平臺的所有版本都提供支持。有關受支持版本的列表,請參見系統要求。

 版本信息
.NET Framework
受以下版本支持:2.0

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章