【问题标题】:Transactionscope throwing exception this platform does not support distributed transactions while opening connection objectTransactionscope 抛出异常此平台在打开连接对象时不支持分布式事务
【发布时间】:2019-05-27 15:25:21
【问题描述】:

TransactionScope 在 .net core 2.2 中引发异常

在这个例子中,我创建了一个scope of TransactioScop。 为一个运行良好的数据库打开 SQL 事务。
在第一个事务之后,我调用commit,它将提交 SQL 事务。 我尝试在创建事务时为另一个数据库打开 call transaction,但系统抛出异常

此平台不支持分布式事务。

试图删除 SQL 事务

c#

using (TransactionScope scop =new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled))
{       
    _db1UOW.Begin(); //creating sql transaction
    await _db1UOW.IDenialDetailsRepositorydb1.InsertDenialDetails(denialsDetails);
    await _db1UOW.IRuleDetailsRepositorydb1.InsertRulesDetails(rulesDetails);
    _db1UOW.Commit(); //commitng sql transaction

    _db2UOW.Begin(); //creating sql transaction (but while opening connection object its throwing exception as This platform does not support distributed transactions)
    await _db2UOW.IRuleDetailsRepository.GetRulesDetails();
    await _db2UOW.IDenialDetailsRepository.InsertDenialDetails(denialsDetails);
    var data = await _db2UOW.IRuleDetailsRepository.InsertRulesDetails(rulesDetails);
    _db2UOW.Commit(); //commitng sql transaction
    scop.Complete();
}

留言

"This platform does not support distributed transactions."  at System.Transactions.Distributed.DistributedTransactionManager.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
   at System.Transactions.TransactionInterop.GetDistributedTransactionFromTransmitterPropagationToken(Byte[] propagationToken)
   at System.Transactions.TransactionStatePSPEOperation.PSPEPromote(InternalTransaction tx)
   at System.Transactions.TransactionStateDelegatedBase.EnterState(InternalTransaction tx)
   at System.Transactions.EnlistableStates.Promote(InternalTransaction tx)
   at System.Transactions.Transaction.Promote()
   at System.Transactions.TransactionInterop.ConvertToDistributedTransaction(Transaction transaction)
   at System.Transactions.TransactionInterop.GetExportCookie(Transaction transaction, Byte[] whereabouts)
   at System.Data.SqlClient.SqlInternalConnection.GetTransactionCookie(Transaction transaction, Byte[] whereAbouts)
   at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx)
   at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
   at System.Data.SqlClient.SqlConnection.Open()

【问题讨论】:

  • 不要同时使用事务范围和Begin/CommitTransaction,除非您真的想要创建分布式事务。使用了 TransactionScope,因此您不必必须使用显式的 Begin/Commit 调用
  • TransactionScope 仅适用于 Windows。不确定您使用的是什么操作系统。
  • 我正在使用带有 Visual Studio 2017 vs 15.9 的 windows 7 我尝试删除 sql 事务

标签: c# sql-server .net-core


【解决方案1】:

.NET Core 不支持分布式事务,因为它需要在每个平台上使用不同的事务管理器。它可能会在未来出现(here 的问题正在进行中),但目前任何需要两个不同资源管理器的事务都会抛出此异常。

相反,您可以协调单独的事务。让两个单独的事务完成它们的工作,然后同时提交它们。第一次提交成功而第二次提交失败的可能性,但对于 SQL Server,这将是非常罕见的情况。比如:

            _db1UOW.Begin(); //creating sql transaction
            await _db1UOW.IDenialDetailsRepositorydb1.InsertDenialDetails(denialsDetails);
            await _db1UOW.IRuleDetailsRepositorydb1.InsertRulesDetails(rulesDetails);

            _db2UOW.Begin(); //creating sql transaction 
            await _db2UOW.IRuleDetailsRepository.GetRulesDetails();
            await _db2UOW.IDenialDetailsRepository.InsertDenialDetails(denialsDetails);
            var data = await _db2UOW.IRuleDetailsRepository.InsertRulesDetails(rulesDetails);

            _db1UOW.Commit(); //commitng sql transaction
            try
            {
               _db2UOW.Commit(); //commitng sql transaction
            }
            catch (Exception ex)
            {
               LogError("Second transaction failed to commit after first one committed.  Administrators may need to fix stuff");
               throw;
            }

或者,如果两个数据库位于同一台服务器上,您可以使用带有单个 SqlConnection 的跨数据库查询来获取单个 SQL Server 事务中的更改。

【讨论】:

  • 开放的 GitHub 问题是github.com/dotnet/corefx/issues/13532
  • 语句“有可能第一个成功而第二个失败,但对于 SQL Server,这将是一种非常罕见的情况。” - 是不真实的。一个事务可能由于多种原因而失败,这正是分布式事务存在的原因!如果您想始终使用分布式事务,这并不是一个好主意...
  • 此时只是提交。否则,两项交易均已完成。所以大多数潜在的交易失败已经发生了。更新了答案以澄清。
  • 有什么更新吗?我尝试了microsoft 的解决方案,不幸的是它不起作用。我不确定这是否可能是由 2014 SQL Server 引起的。或者System.Data.SqlClient(因为Microsoft.Data.SqlClient没有连接到公司服务器)
  • 好吧,没关系,我只是注意到它是框架而不是核心的解决方案。我看到某种分布式事务可能会出现在 7.0 版本中(仅限 Windows)
猜你喜欢
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
相关资源
最近更新 更多