0

MS Sql Server 2008 を使用して Windows サービスで実行するように NHibernate をセットアップしました。通常の TransactionScope を使用して、操作がアトミックであることを確認します。Hibernate は、アセンブリごとにセッション ファクトリを作成するように設定されています。

3 つの異なるアセンブリからオブジェクトに変更を書き込みたいと考えています。一度に 1 つまたは 2 つのアセンブリを操作するとすべて正常に動作しますが、3 つ目のアセンブリからの読み取りを追加すると問題が発生します。

つまり、2 つのアセンブリ内のオブジェクトの読み取り/書き込みは正常に機能しますが、アセンブリからオブジェクトを追加すると問題が発生します。ただし、他の 2 つのアセンブリのオブジェクトを操作せずに 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 に答える