使用相同连接的 TransactionScope 和方法调用

TransactionScope and method call that uses the same connection

我正在使用 TransactionScope 使包含多个 sql 语句的方法成为事务性的。现在我需要调用第二种方法,它也使用相同的连接,我在 connection.Open():

收到以下异常

Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.

所以这是伪代码:

public static void Method1()
{
    using (TransactionScope scope = new TransactionScope())
    {
        bool success = true; // will be set to false in an omitted catch
        using (var connection = new SqlConnection(ConnectionString1))
        {
           // ...
           if(somethingHappened)
               Method2();
        }
        if(success)
            scope.Complete();
    }
}

public static void Method2()
{
    using (var connection = new SqlConnection(ConnectionString1))
    {
        connection.Open(); // BOOOM!
        // ...
    }
}

如何在不重复 Method1Method2 的代码的情况下避免此异常?

我不知道确切的答案,但我会将连接设为成员,并跟踪它是否打开。

然后在 Method1 和 Method2 中,我将通过一些 GetConnection() 获取连接,这将在首次使用时打开连接。


阅读评论后,我建议使用私有的 DoMethod2,它接受一个连接对象。

如果在同一个 TransactionScope 下打开了一个以上的连接,它将自动升级为 DTC。

您需要在调用 Method2 之前关闭第一个连接。

public static void Method1()
{
    using (TransactionScope scope = new TransactionScope())
    {
        bool success = true; // will be set to false in an omitted catch

        bool isSomethingHappened
        using (var connection = new SqlConnection(ConnectionString1))
        {
           isSomethingHappened = // Execute query 1
        }

       if(somethingHappened)
           Method2();

        if(success)
            scope.Complete();
    }
}

同一事务作用域下的嵌套连接将提升为分布式事务。

来自 SQL 服务器 2008 及以上版本的同一事务范围内的多个(非嵌套)连接将不会提升为分布式事务。

有关详细信息,请参阅 this 问题