【问题标题】:NHibernate transaction problem with multiple sessions多个会话的 NHibernate 事务问题
【发布时间】:2010-11-02 16:59:32
【问题描述】:

我已将 NHibernate 设置为使用 MS Sql Server 2008 在 Windows 服务中运行。我使用常规 TransactionScope 来确保操作是原子的。 NHibernate 设置为为每个程序集创建一个会话工厂。

我想对来自 3 个不同程序集的对象进行更改。 当我当时使用一两个程序集时,一切正常,但是当我从第三个程序集添加读取时,我遇到了问题。

即读取/写入两个程序集中的对象可以正常工作,从程序集中添加对象会产生问题。但是,从第三个程序集读取而不使用其他两个程序集的对象也可以正常工作。我有一种感觉,这些会话正在给彼此制造问题。

我的代码是这样的:

using (var scope = new TransactionScope())
{
//Read object 1
//Do changes to object 2
//Do changes to object 3
scope.Complete();
}

当我尝试完成我的事务范围(通过 scope.Complete())时,我收到以下错误消息:

System.Data.SqlClient.SqlException: Microsoft Distributed Transaction Coordinator (MS DTC) has stopped this transaction.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment enlistment) 
System.Transactions.TransactionAbortedException: The transaction has aborted.
at System.Transactions.TransactionStatePromotedAborted.PromotedTransactionOutcome(InternalTransaction tx)
at System.Transactions.TransactionStatePromotedEnded.EndCommit(InternalTransaction tx)
at System.Transactions.CommittableTransaction.Commit()
at System.Transactions.TransactionScope.InternalDispose()
at System.Transactions.TransactionScope.Dispose()

有什么想法吗?

【问题讨论】:

  • 为什么不对 3 个程序集使用一个会话工厂?有什么特殊需要吗?

标签: sql-server nhibernate transactions transactionscope msdtc


【解决方案1】:

首先检查您是否正确地同时使用了 nHibernate 和 TransactionScope。以下是应该如何完成的(取自Avoiding Leaking Connections With NHibernate And TransactionScope):

        using (var scope = new TransactionScope(TransactionScopeOption.Required))
        {
            using (var session = sessionFactory.OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                // do what you need to do with the session
                transaction.Commit();
            }
            scope.Complete();
        }

如果跨多个事务“重用”会话,您遇到的错误很常见。我发现这是一个痛苦的世界,因为分布式事务是在后台线程上提交和回滚的,所以你不知道什么时候可以重用它们。 nHibernate 代码也不是线程安全的。因此我建议永远不要重复使用会话,始终按照上面的代码销毁它们。

【讨论】:

  • 我认为在 NHibernate 2.1 中,TransactionScope 是开箱即用的 (stackoverflow.com/questions/646318/…)。
  • 特定条件下支持。以上是最安全的使用方法。我遇到了回滚问题,导致连接泄漏。当我尝试修复它时,我遇到了其他问题,例如您遇到的问题。最后,上述方法奏效了。
  • 好的。感谢您的回复!你知道我在哪里可以找到关于 NHibernate 如何与 TransactionScopes 一起工作的文档吗?我尝试过 NHForge 和《NHibernate in action》一书,但似乎都有些过时了。
  • 对不起,我没有。我从博客、讨论、源代码和经验拼凑而成。
猜你喜欢
  • 2012-03-30
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多