34

NHibernateでのTransactionScopeの使用の概要を教えてもらえますか?セッション/IEnlistmentNotificationなどで何か特別なことをする必要がありますか?これを機能させるには?気になる落とし穴はありますか?たとえば、休止状態のトランザクションをすべて置き換えることはできますか?

var transaction = session.BeginTransaction();
try
{
    // code
    transaction.Commit();
}
catch (Exception)
{
    transaction.Rollback();
}

これとともに?:

using (var scope = new TransactionScope())
{
    // code
    scope.Complete();
}
4

6 に答える 6

19

私はしばらくの間 nHibernate 2.1 を使用してきました。いくつかの生産上の問題とかなりの数のバリエーションを試した後、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();
        }

MSMQ と WCF を使用しているため、アンビエント トランザクションを使用する必要がありました。

session.BeginTransaction() を使用しないと接続リークが発生することがわかりました。また、トランザクションをコミットした後にセッションを再利用すると、競合状態が発生することもわかりました (nHibernate はスレッド セーフではなく、DTSC コミット/ロールバックはバックグラウンド スレッドで発生します)。

于 2010-11-03T08:46:26.563 に答える
7

さまざまなベンダーを使用してこれをテストしましたが、うまくいきます。「scope.Complete()」がない場合、トランザクションはロールバックされます。複数の永続的なリソースがある場合は、関連するマシンを MSDTC で実行する必要がある場合があります。その場合、MSDTC は自動的にアンビエント ADO.NET トランザクションを検出し、すべてを管理します。

于 2009-03-30T19:37:36.743 に答える
6

一部の人がすでに言っているように、いくつかの制約を尊重する限り、NHibernate トランザクションをこれに置き換えることができると思います。

  • かなり新しい NHibernate バージョン ( >=3.1 ) を使用してください。
  • 基礎となる ADO.NET データ プロバイダーは、TransactionScope をサポートする必要があります (SQL-Server では OK、Oracle >= 10 で ODP.NET を使用)。
  • TransactionScope内にNH セッションを作成して、確実に参加できるようにします。
  • NHibernateのフラッシュを手動で処理します。ここここも参照してください。
  • 分散トランザクションを準備します。1 つのスコープで複数のセッションを作成すると、最初のローカル トランザクションが分散トランザクションに昇格する可能性があります。これは、ODAC 11.2.0.3.20 を使用する Oracle 11.2 DB で同じ接続文字列を使用しても発生することがわかりました。SQL-Server 2008 R2 では昇格しませんでした。(ところで、これは、ローカル トランザクションの場合は null である Transaction.Current.TransactionInformation.DistributedIdentifier を見ることで確認できます。) 分散トランザクションにはいくつかの利点がありますが、コストが高くなり、セットアップに余分な手間がかかります。(Oracleでこれを行う方法はこちらを参照してください)。Oracle で昇格が起こらないようにするには、接続文字列で " Promotable Transaction =local" を設定します。これにより、一部のコードがそうしようとすると例外が作成されます。

それがすべてであることを願っています;-)

PS: オラクルの詳細を追加しました。これは、私の懸念や他の人が利益を得る可能性があるためです。

于 2013-02-28T13:06:33.700 に答える
6

上記は、SQL Server 2005/2008 などの軽量トランザクション マネージャーの使用をサポートする接続プロバイダーを使用している場合に問題なく動作します。

SQL Server 7/2000 を使用している場合、1 つのデータベース/リソースにヒットしただけでも、すべてのトランザクションが分散トランザクションになります。これは、おそらくほとんどの場合、あなたが望むものではなく、パフォーマンスの点で高価になります。

したがって、接続プロバイダーとデータベース サーバーの組み合わせが TransactionScope での使用に適しているかどうかを確認してください。

于 2009-07-06T09:55:07.310 に答える
1

NH-2107に関連するコメントの Fabio Maulo によると:

TransactionScope を使用できます。NH のトランザクションも引き続き使用する必要があります。TransactionScope の使用法が NH のトランザクションの使用を避けることを意味することをどこで読んだことがありますか?

NHibernate のトランザクションを明示的に使用する必要はないと考えていましたが、明らかにそれがベスト プラクティスです

于 2010-09-14T12:46:35.133 に答える
1

また、TransactionScope を使用している場合は、NHibernate 2.1 にアップグレードしてください。NH が本当に TransactionScope とうまく統合されたのは 2.1 だけです。

于 2009-11-16T20:14:34.733 に答える