1

自分のアーキテクチャで作業単位が間違って設定されている可能性があると思います。これが私が現在持っているものです(順序を示すためにインデントされています):

HttpRequest.Begin()
  UnitOfWork.Begin()
    Session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted);

ここでは、NHibernateを使用してクラッドを実行するためにさまざまなサービスを呼び出します。データベースに変更(更新/保存)を行う場合は、次のコードを呼び出します。

        using (var transaction = unitOfWork.Session.BeginTransaction())
        {
            try
            {
                // These are just generics
                ret = (Key)unitOfWork.Session.Save(entity);
                transaction.Commit();
                rb.unitOfWork.Session.Clear();
            }
            catch
            {
                transaction.Rollback();
                rb.unitOfWork.Session.Clear();
                rb.unitOfWork.DiscardSession();
                throw;
            }
        }

HttpRequestが終了したら、次の手順を実行します。

      UnitOfWork.Commit()
    Transaction.Commit() // This is my sessions transaction from the begin above

大規模なバッチプロセスをロールバックできるという問題が発生しています。上記のように、CRUDレイヤーでトランザクションをコミットしているため、トランザクションはアクティブではなくなり、UnitOfWorkでロールバックしようとすると、トランザクションがすでにコミットされているため、何も実行されません。CRUDレイヤーでコードをコミットする理由は、データベースを長時間ロックすることなく、データをできるだけ早く永続化できるようにするためです。

上記のような状況で取るべき最善の行動方針は何ですか?バッチジョブをコミットせず、ジョブの最後にコミットを処理する特別なCRUD操作を行うだけですか、それともUnitOfWorkとSession Per Requestのロジックに欠陥がありますか?助言がありますか?

4

1 に答える 1

8

リクエストごとのセッションパターンが非常に人気がある理由と、作業単位のマイクロ管理に起因する可能性のある問題を発見しました。

通常、各Webリクエストでは、そのリクエスト内で実行する必要があるすべてが1つの作業単位と見なすことができるため、その1つのWebリクエスト中に1つの作業単位と1つのNHibernateセッションのみを開く必要があるのは当然です。

また、質問の次の文のためにNHibernateがどのように機能するかについて少し混乱していると思います。「CRUDレイヤーでコードをコミットする理由は、データベースをロックせずにできるだけ早くデータを永続化できるようにするためです。長過ぎる。"

NHibernateによってデータベースがロックされることはありません。ISession.Save(entity)を呼び出すたびに、ISession.Flush()またはITransaction.Commit()を呼び出さない限り、データベースには何も書き込まれず、挿入されるアイテムのキューに追加されます。 Webリクエストの最後に現在のトランザクションがコミットされると、データベースで更新されます。

したがって、リクエストごとのセッションは次のように設定する必要があります。

void Application_BeginRequest()
{
    // Start your unit of work, open a session and begin a transaction
}

// Do all of your work ( Read, insert, update, delete )

void Application_EndRequest()
{
    try
    {
        // UnitOfWork.Current.Transaction.Commit();
    }
    catch( Exception e )
    {
        // UnitOfWork.Current.Transaction.Rollback();
    }
}

もちろん、これと同じことを行う方法はたくさんありますが、これはリクエストパターンごとのセッションの基本です。Webリクエスト全体に対して1つのセッションのみです。

于 2012-11-03T05:24:57.343 に答える