Spring.NET从2.0.2升级到3.0.2后出现TransactionException问题求助
问题描述
将Spring.NET包从2.0.2版本升级到3.0.2版本后,[Transaction]属性拦截器的行为发生变化,出现如下异常:
System.Transactions.TransactionException HResult=0x80131501 Message=The operation is not valid for the state of the transaction. Source=System.Transactions StackTrace: at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType) at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType) at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification) at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx) at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(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.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) at System.Data.SqlClient.SqlConnection.Open() Inner Exception 1: TransactionPromotionException: Failure while attempting to promote transaction. Inner Exception 2: SqlException: Distributed transactions (DTC) are not supported with transactions that access memory optimized tables or natively compiled modules.
除版本升级外无其他变更,需解释异常原因并提供解决办法。
异常原因分析
- Spring.NET 3.0.2版本对
[Transaction]拦截器的默认事务处理逻辑做了调整,默认启用了事务自动提升机制——当事务内出现跨连接操作时,会自动将本地事务升级为分布式事务(DTC)。 - 业务逻辑中涉及了SQL Server的内存优化表或原生编译模块,而SQL Server明确禁止这类对象参与分布式事务,因此当事务被尝试提升为DTC时,底层SQL客户端抛出了不支持的异常。
解决办法
- 显式配置事务属性,禁用自动提升:在
[Transaction]属性中指定合适的事务传播行为与隔离级别,确保事务保持为本地事务。例如:[Transaction(TransactionPropagation.Required, IsolationLevel = IsolationLevel.Snapshot)]Snapshot隔离级别是内存优化表支持的隔离级别之一,同时可避免触发事务提升。 - 确保单事务内复用数据库连接:检查代码中是否存在同一事务内多次打开新数据库连接的情况,统一复用已有的连接,避免触发Spring.NET的事务提升逻辑。
- 调整内存优化表的事务策略:内存优化表仅支持本地事务,且要求使用
SNAPSHOT或READ COMMITTED SNAPSHOT隔离级别,确保事务配置符合此要求。 - 修改Spring.NET配置还原旧行为:如果暂时无法调整业务代码,可以在Spring.NET的配置文件中修改事务拦截器的设置,关闭自动事务提升,还原到2.0.2版本的事务处理逻辑。
内容的提问来源于stack exchange,提问作者user1193850
相关产品推荐
相关产品推荐

