3

バックグラウンド

nhibernate セッション管理に関するあらゆる種類のブログとドキュメントを読みました。私の問題は、winforms と webforms の両方に必要なことです。そうです、winforms (windows .exe) と webforms (asp.net web) アプリケーションの両方で同じデータ レイヤーを使用しています。作業単位パターンについて少し読んだことがあり 、winforms に適しています。nhibernate セッションを HttpRequest.Current.Items に格納することは、Web アプリに適した方法のようです。しかし、コンボ取引はどうですか?同じ nhibernate データ レイヤーを使用する必要がある Web アプリ、Windows アプリ、および WCF サービスがあります。では、私の質問に戻ります...

私はこのデザインを使用する予定です: NhibernateBestPracticesのように私の Web アプリで:

private ISession ThreadSession {
    get {
        if (IsInWebContext()) {
            return (ISession)HttpContext.Current.Items[SESSION_KEY];
        }
        else {
            return (ISession)CallContext.GetData(SESSION_KEY); 
        }
    }
    set {
        if (IsInWebContext()) {
            HttpContext.Current.Items[SESSION_KEY] = value;
        }
        else {
            CallContext.SetData(SESSION_KEY, value); // PROBLEM LINE HERE!!!
        }
    }
}

問題

私のWindowsアプリでこのコードを使用するときに私が抱えている問題は、次の行にあります

CallContext.SetData(SESSION_KEY, value);

CallContext() が正しいことを理解していれば、nhibernate セッションがメイン アプリケーション スレッドの一部として保存されるため、Windows アプリの全期間にわたってセッションを開いたままにできます。また、休止状態のセッションを長時間開いたままにしておくことについて、あらゆる種類の悪いことを聞いたことがありますが、設計上、長時間開いたままにすることは意味がないことを知っています。私の仮定がすべて正しければ、上記のコード行はノー、ノーです。

これらすべてを考慮して、上記の行を、Windows アプリでより頻繁に nhibernate セッションを破棄するものに置き換えたいと思います。HttpRequest の有効期間に似たもの。nhibernate セッション (またはトランザクション) とそれをいつ開いて閉じるかを Windows クライアントに任せたくありません。これを自動的にトリガーしたいと思います。

質問

したがって、nhibernate セッションを Windows アプリのどこに保存すれば、データベース要求ごとに (つまり、クライアントが DB を呼び出すたびに) トランザクションを自動的に開始および終了できますか (つまり、クライアント以外のもの)。 )?

**更新**

作業単位パターンを実装する方法に関する 2 つのリンクを次に示します。

http://msdn.microsoft.com/en-us/magazine/dd882510.aspx

http://www.codeinsanity.com/2008/09/unit-of-work-pattern.html

4

2 に答える 2

1

各アプリは、IUnitOfWorkStorage などのインターフェースの共通実装を提供できます

public interface IUnitOfWorkStorage
{
    void StoreUnitOfWork(IUnitOfWork uow);
}

IUnitOfWork は、次のように見える ISession のラッパーにすることができます

public interface IUnitOfWork
{
   void Begin();
   void End();
}

Beginセッションを開いてトランザクションを開始する一方Endで、トランザクションをコミットしてセッションを閉じる可能性があります。IUnitOfWorkStorageしたがって、WebApp 用と Windows アプリ用の2 つの実装を持つことができます。Web アプリは HttpContext.Current などを使用でき、Windows アプリは、UnitOfWork を終了するアクションの最後に配置される単純なオブジェクト ストアを提供できます。

于 2011-01-29T15:18:00.413 に答える
1

私は次のコードを使用して終了しました。それが私のアプリに課した唯一の「負担」は単体テストでした。私はむしろ、本番コードであるセッション固有の情報でそのコードを台無しにしたいと思います。質問で述べたのと同じコードを保持し、このクラスを単体テスト プロジェクトに追加しました。

namespace MyUnitTests
{
    /// <summary>
    /// Simulates the IHttpModule class but for windows apps.  
    /// There's no need to call BeginSession() and EndSession() 
    /// if you wrap the object in a "using" statement.
    /// </summary>
    public class NhibernateSessionModule : IDisposable
    {
        public NhibernateSessionModule()
        {
            NHibernateSessionManager.Instance.BeginTransaction();
        }

        public void BeginSession()
        {
            NHibernateSessionManager.Instance.BeginTransaction();
        }

        public void EndSession()
        {
            NHibernateSessionManager.Instance.CommitTransaction();
            NHibernateSessionManager.Instance.CloseSession();
        }

        public void RollBackSession()
        {
            NHibernateSessionManager.Instance.RollbackTransaction();
        }

        #region Implementation of IDisposable

        public void Dispose()
        {
            // if an Exception was NOT thrown then commit the transaction
            if (Marshal.GetExceptionCode() == 0)
            {
                NHibernateSessionManager.Instance.CommitTransaction();
            }
            else
            {
                NHibernateSessionManager.Instance.RollbackTransaction();
            }
            CloseSession();
        }

        #endregion
    }
}

上記のクラスを使用するには、次のようにします。

[Test]
public void GetByIdTest()
{
    // begins an nhibernate session and transaction
    using (new NhibernateSessionModule())
    {
        IMyCustomer myCust = MyCustomerDao.GetById(123);
        Assert.IsNotNull(myCust);           
    } // ends the nhibernate transaction AND the session
}

注:このメソッドを使用している場合は、この投稿のように Dao クラスからクエリを実行するときに、セッションを「using」ステートメントでラップしないようにしてください。セッションを自分で管理し、クエリごとに 1 つのセッションよりも少し長く開いたままにしておくため、セッションを閉じているすべての場所を取り除き、NhibernateSessionModule にそれを行わせる必要があります (Web アプリまたは Windows アプリ) )。

于 2011-02-02T17:45:50.287 に答える