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

本文关键字:嵌套 transactionscope 数据库 Azure SQL | 更新日期: 2023-09-27 18:07:42

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

我使用下面的代码(。Net 4.5.1,我的代码都是异步的,它是ASP。. Net MVC with EF6.1):

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?

官方文件说:

Microsoft Azure SQL数据库不支持分布式事务,即影响多个资源的事务。有关详细信息,请参见分布式事务(ADO.NET)。

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

事务提升发生在打开多个连接到不同的服务器或数据库在一个TransactionScope内,或者当您在一个系统中登记多个连接。通过使用EnlistTransaction方法。事务提升也发生在打开到同一服务器的多个并发连接数据库,可以在相同的TransactionScope中,也可以使用EnlistTransaction方法。

从3.5版本开始,如果执行以下操作,事务将不会被提升并发连接的连接字符串就是相同。有关事务和避免事务的更多信息晋升,见制度。与SQL Server的事务集成(ADO.NET) .

没有回答我的任何问题

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

尝试将此添加到您的连接字符串中,它将打开多个活动结果集。这应该可以阻止MSDTC问题;尽管我对此不太确定。

MultipleActiveResultSets=True;

对于额外信息,嵌套事务不是真正的嵌套事务。

MSDN:在单个事务中关闭连接并重新打开连接时,可能会将事务提升到DTC。因为实体框架会自动打开和关闭连接,所以你应该考虑手动打开和关闭连接,以避免事务促进。

如何从对象上下文中手动打开连接

Azure SQL数据库现在支持从TransactionScope将事务提升为分布式事务。这使得以前由于不支持MSDTC而无法使用TransactionScope成为可能。因此,您不一定需要像前面的回复中建议的那样控制连接的打开和关闭。参见:https://azure.microsoft.com/en-us/documentation/articles/sql-database-elastic-transactions-overview/。

还需要注意的是,Azure DB目前仍然不完全支持多活动结果集。