开发者

NHibernate transaction problem with multiple sessions

开发者 https://www.devze.com 2023-01-23 08:19 出处:网络
I have set up NHibernate to run in a windows service with MS Sql Server 2008. I use a regular TransactionScope to ensure that the operation is atomic.

I have set up NHibernate to run in a windows service with MS Sql Server 2008. I use a regular TransactionScope to ensure that the operation is atomic. NHibernate is set up to create a session factory per assembly.

I want to write changes to objects from 3 different assemblies. Everything works fine when I work with one or two assemblies at the time, but when I add reading from a third assembly I run into problems.

I.e. Reading/Writing to and from objects in two assemblies works fine, adding objects from the assembly creates problems. However, reading from the third assembly without working with objects from the other two assemblies also works fine. I have a feeling that the sessions are creating problems for each other.

My code is like this:

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

When I try to complete my transaction scope (via scope.Complete()) I get the following error message:

System.Data.SqlClient.SqlException: Microsoft Distributed Transaction Coordinator (MS DTC) has stopped this trans开发者_运维技巧action.
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()

Any thoughts?


Firstly check that you are correctly using nHibernate and TransactionScope together. Here is how it should be done (taken from 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();
        }

The error you are getting is common if are 'reusing' sessions across multiple transactions. I found it to be a world of pain, as distributed transactions are committed and rolled back on a background threads so you cannot know when you can reuse them. Also the nHibernate code is not thread safe. Hence I suggest never reuse sessions, always destroy them as per the code above.

0

精彩评论

暂无评论...
验证码 换一张
取 消