具有多个会话的NHibernate事务问题

时间:2010-11-02 16:59:32

标签: sql-server nhibernate transactions transactionscope msdtc

我已经将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()

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

首先检查您是否正确使用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代码也不是线程安全的。因此,我建议永不重用会话,始终按照上面的代码销毁它们。