使用TransactionScope时出现异常“操作无法适用于事务状态”。

21
我们在服务器#1上有一个Web服务,并在服务器#2上有一个数据库。Web服务使用事务范围来生成分布式事务,一切都正确。
我们在服务器#3上有另一个数据库。我们遇到了一些问题,重新安装了操作系统和软件。我们配置了MSDTC并尝试使用来自服务器#1的Web服务与此服务器上的数据库进行通信。现在,在事务范围内的第一个选择语句之后,我们会得到“事务状态无效”的异常。如果Web服务正在使用事务范围,则此异常会在每个Web服务请求中发生。服务器#2和服务器#3几乎相似。唯一的区别可能只是设置。所有服务器都安装了.NET Framework 3.5 SP1和SQL Server SP3。
完整的堆栈跟踪:
System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction) in System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification) in System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction t in System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction t in System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction) in System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction) in System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) in System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) in System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) in System.Data.SqlClient.SqlConnection.Open() in NHibernate.Connection.DriverConnectionProvider.GetConnection() in NHibernate.Impl.SessionFactoryImpl.OpenConnection()
我搜索了这条消息,但没有找到任何适当的解决方案。那么,我应该检查哪些设置以及应该做什么来解决它?

你使用的是哪个操作系统?你如何准确地配置 MSDTC? - Remus Rusanu
你正在使用TransactionScope()构造函数的哪种形式? - gprasant
嗨,Lanfear,你解决了这个问题吗?我们在测试环境中遇到了相同的错误。在开发环境中相同的代码运行良好。 - Samir Vaidya
2个回答

31

Lanfear,我遇到了同样的错误信息,并找到了解决方案。您的情况可能不同,但希望以下知识对您有用。

System.Transactions.Transaction.Current.TransactionInformation.Status 会返回当前事务的状态。

在每个抛出消息为 The operation is not valid for the state of the transaction 的异常中,当我使用调试器调试时,我看到异常抛出前状态是“已中止(Aborted)”。

在我的情况下,问题是由于嵌套两个事务并错误地中止了两个事务而导致的。显然,如果您使用带有两个嵌套事务的 TransactionScope 默认构造函数 New TransactionScope(),中止内部事务也会中止外部事务。 解决方案是使用构造函数 New TransactionScope(TransactionScopeOption.RequiresNew),这将创建一个新的内部事务,中止它将不会中止外部事务。

这解决了我的问题。


3
System.Transactions.Transaction.Current.TransactionInformation.Status帮助我准确地确定了事务何时被中止。 - Adam Marshall
@AdamMarshall 有没有一个使用 TransactionInformation.Status 的真实世界的样例? - Kiquenet

5
启用分布式事务协调器解决了我的问题(这是在具有Web服务和数据库的两台计算机上完成的。不确定是否需要对Web服务进行操作)。
我按照此处描述的步骤启用了DTC并向Windows防火墙添加了例外:启用 Windows Server 2008 的网络 DTC 访问

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接