如何对Azure SQL数据库使用嵌套的TransactionScopes

时间:2015-08-13 15:39:18

标签: c# azure transactions async-await msdtc

我目前正在尝试使用嵌套的事务作用域来对Azure SQL数据库进行数据库访问。

我正在使用以下代码(.Net 4.5.1,我的代码一直是异步,它是带有EF6.1的ASP.Net MVC):

public async Task Test()
{
    // In my actual code, the DbContext is injected within the constructor
    // of my ASP.Net MVC Controller (thanks to IoC and dependency injection)
    // The same DbContext instance is used for the whole HttpRequest
    var context = new TestContext();

    using (var t1 = StartTransactionForAsync())
    {
        using (var t2 = StartTransactionForAsync())
        {
            context.Users.Add(new User { Name = Guid.NewGuid().ToString() });
            await context.SaveChangesAsync();

            t2.Complete();
        }
        ... // Some more code here
        t1.Complete();
    }
}

private static TransactionScope StartTransactionForAsync()
{
    return new TransactionScope(
        TransactionScopeOption.Required,
        new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },
        TransactionScopeAsyncFlowOption.Enabled);
}

一切都很好,除非有时TransactionScope升级到MSDTC,(显然)Azure SQL数据库不支持。所以我有时会收到以下错误:

  

分布式事务管理器(MSDTC)的网络访问已经完成   禁用。请在安全性中启用DTC以进行网络访问   使用组件服务管理的MSDTC配置   工具。

我可以将Enlist=False添加到我的连接字符串中,但它会破坏上面的代码,因为即使外部TransactionScope在没有Complete的情况下被处置,内部事务仍会插入数据库

我的目标是单个数据库,使用单个实体框架上下文表示我的整个HttpRequest始终使用相同的连接字符串< /强>

所以我的问题是:

  • 是Azure SQL数据库支持的嵌套事务吗?
  • 为什么上面的代码有时会升级到MSDTC?

official documentation说:

  

Microsoft Azure SQL数据库不支持分布式   事务,它们是影响多个资源的事务。   有关更多信息,请参阅分布式事务(ADO.NET)。

     

从版本2.0开始,应用程序事务可能是   自动提升为分布式事务。这适用于   使用System.Data.SqlClient类执行的应用程序   System.Transactions上下文中的数据库操作   交易。

     

当您打开多个连接时,会发生事务促销   TransactionScope中的不同服务器或数据库,或者您   使用,在System.Transactions对象中登记多个连接   EnlistTransaction方法。交易促销也发生在   您打开多个并发连接到同一服务器和   数据库在同一个TransactionScope中或使用   EnlistTransaction方法。

     

从版本3.5开始,如果是,则不会提升交易   并发连接的连接字符串正好是   相同。有关事务和避免事务的更多信息   升级,请参阅System.Transactions与SQL Server集成   (ADO.NET)。

没有回答我的任何问题。

2 个答案:

答案 0 :(得分:1)

MSDN:在单个事务中关闭连接并重新打开连接时,可能会向DTC提升事务。由于实体框架会自动打开和关闭连接,因此您应该考虑手动打开和关闭连接以避免交易促销。

避免这种情况:How to Manually Open the Connection from the Object Context

答案 1 :(得分:0)

Azure SQL数据库现在支持从TransactionScope将事务提升到分布式事务。现在可以使用TransactionScope,因为之前不可能使用,因为MSDTC不受支持。因此,您不一定需要按照上一个回复中的建议控制连接打开和关闭。见:https://azure.microsoft.com/en-us/documentation/articles/sql-database-elastic-transactions-overview/

另请注意,Azure DB当前仍不完全支持多个活动结果集。