0

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

有什么想法吗?

4

1 回答 1

0

首先检查您是否正确地同时使用了 nHibernate 和 TransactionScope。这是应该如何完成的(取自避免使用 NHibernate 和 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 代码也不是线程安全的。因此我建议永远不要重用会话,总是按照上面的代码销毁它们。

于 2010-11-03T07:17:42.177 回答