使用 System.Transactions

System.Transactions 命名空间是 Microsoft .NET Framework 2.0 版中的新命名空间。它提供与 ADO.NET 和 SQL Server 公共语言运行时 (CLR) 集成完全集成的新事务框架。System.Transactions.TransactionScope 类通过在分布式事务中隐式登记连接,使代码块成为事务代码。您必须在 TransactionScope 标记的代码块的末尾调用 Complete 方法。如果未调用 Complete 方法,将在程序执行离开代码块时调用 Dispose 方法,从而导致停止使用该事务。如果已引发导致代码离开范围的异常,则将该事务视为停止使用。

建议您使用 using 块,以便确保在退出 using 块时对 TransactionScope 对象调用 Dispose 方法。提交或回滚挂起事务失败可能会严重降低性能,因为 TransactionScope 的默认超时值为 1 分钟。如果未使用 using 语句,必须在 Try 块中执行所有工作,并在 Finally 块中显式调用 Dispose 方法。

如果在 TransactionScope 内发生异常,则将该事务标记为不一致,并放弃使用该事务。释放 TransactionScope 时将回滚该事务。如果未发生异常,则提交参与的事务。

仅当正在访问本机和远程数据源或外部资源管理器时,才应使用 TransactionScope。这是因为 TransactionScope 始终导致提升事务,即使仅在上下文连接内使用该事务也是如此。

注意注意

默认情况下,TransactionScope 类创建 System.Transactions.Transaction.IsolationLevel 为 Serializable 的事务。根据您的应用程序,您可能希望考虑降低隔离级别,以避免在应用程序中发生争用激烈的情况。

注意注意

建议您在分布式事务内针对远程服务器仅执行更新、插入和删除操作,因为这些操作占用大量数据库资源。如果将在本地服务器上执行该操作,则不需要分布式事务,而使用本地事务。SELECT 语句可能会不必要地锁定数据库资源,在某些情况下,可能必须使用事务进行选择。应在事务范围之外执行任何非数据库工作,除非它涉及其他事务资源管理器。虽然事务范围内的异常可以避免提交该事务,但是 TransactionScope 类无法回滚在该事务自身范围之外对代码所做的任何更改。如果需要在事务回滚时采取某一操作,必须写入您自己的 System.Transactions.IEnlistmentNotification 接口实现,并在该事务中显式登记。

示例

若要使用 System.Transactions,必须引用 System.Transactions.dll 文件。

下面的代码演示如何创建可根据两个不同 SQL Server 实例进行提升的事务。这些实例由两个不同的 System.Data.SqlClient.SqlConnection 对象表示,它们包装在 TransactionScope 块中。该代码创建带有 using 语句的 TransactionScope 块,并打开第一个在 TransactionScope 中自动登记的连接。该事务最初作为轻型事务登记,而不是完全分布式事务。代码假定存在条件逻辑(为简洁起见,已省略该逻辑)。代码仅在需要时打开第二个连接,并在 TransactionScope 中登记。打开该连接后,事务将自动提升为完全分布式事务。该代码随后调用 TransactionScope.Complete,这将提交事务。当退出连接的 using 语句时,代码释放两个连接。TransactionScope 的 using 块终止时,将自动调用 TransactionScope 的 TransactionScope.Dispose 方法。如果在 TransactionScope 块的任一点引发异常,则不会调用 Complete,并且分布式事务将在释放 TransactionScope 时回滚。

Visual Basic

Using transScope As New TransactionScope()
    Using connection1 As New SqlConnection(connectString1)
        ' Opening connection1 automatically enlists it in the 
        ' TransactionScope as a lightweight transaction.
        connection1.Open()

        ' Do work in the first connection.

        ' Assumes conditional logic in place where the second
        ' connection will only be opened as needed.
        Using connection2 As New SqlConnection(connectString2)
            ' Open the second connection, which enlists the 
            ' second connection and promotes the transaction to
            ' a full distributed transaction.
            connection2.Open()

            ' Do work in the second connection.

        End Using
    End Using

    ' Commit the transaction.
    transScope.Complete()
End Using

C#

using (TransactionScope transScope = new TransactionScope())
{
    using (SqlConnection connection1 = new 
       SqlConnection(connectString1))
    {
        // Opening connection1 automatically enlists it in the 
        // TransactionScope as a lightweight transaction.
        connection1.Open();

        // Do work in the first connection.

        // Assumes conditional logic in place where the second
        // connection will only be opened as needed.
        using (SqlConnection connection2 = new 
            SqlConnection(connectString2))
        {
            // Open the second connection, which enlists the 
            // second connection and promotes the transaction to
            // a full distributed transaction. 
            connection2.Open();

            // Do work in the second connection.
        }
    }
    //  The Complete method commits the transaction.
    transScope.Complete();
}

请参阅

概念