1

を定義domain modelしたら、残りの作業を行う方法を理解したいと思います。


データ アクセス層

UnitOfWork私は以前に、独自の実装をコーディングする必要がないことを読んでいISessionました (それを行う方法について多くの情報を見つけました)。だから私はかなり混乱しています..私は次のようなリポジトリインターフェースを持っています:

public interface IRepository<T> where T: AbstractEntity<T>, IAggregateRoot
{
    T Get(Guid id);
    IQueryable<T> Get(Expression<Func<T, Boolean>> predicate);
    IQueryable<T> Get();
    T Load(Guid id);
    void Add(T entity);
    void Remove(T entity);
    void Remove(Guid id);
    void Update(T entity);
    void Update(Guid id);
}

具体的な実装には、次の 2 つのオプションがあります。

オプションA

ISessionFactoryコンストラクターを介して注入し、次のようなものを用意します。

public class Repository<T> : IRepository<T> where T : AbstractEntity<T>, IAggregateRoot
{
    private ISessionFactory sessionFactory;

    public Repository(ISessionFactory sessionFactory)
    {
        this.sessionFactory = sessionFactory;
    }
    public T Get(Guid id)
    {
        using(var session = sessionFactory.OpenSession())
        {
            return session.Get<T>(id);
        }
    }
}

オプション B

NHibernateHelperクラスを使用することです

using(var session = NHibernateHelper.GetCurrentSession())
{
    return session.Get<T>(id);
}

どこNHibernateHelperですか

internal sealed class NHibernateHelper
{
    private const string CurrentSessionKey = "nhibernate.current_session";
    private static readonly ISessionFactory sessionFactory;

    static NHibernateHelper()
    {
        sessionFactory = new Configuration().Configure().BuildSessionFactory();
    }

    public static ISession GetCurrentSession()
    {
        HttpContext context = HttpContext.Current;
        ISession currentSession = context.Items[CurrentSessionKey] as ISession;

        if(currentSession == null)
        {
            currentSession = sessionFactory.OpenSession();
            context.Items[CurrentSessionKey] = currentSession;
        }

        return currentSession;
    }

    public static void CloseSession()
    {
        HttpContext context = HttpContext.Current;
        ISession currentSession = context.Items[CurrentSessionKey] as ISession;

        if(currentSession == null)
        {                
            return;
        }

        currentSession.Close();
        context.Items.Remove(CurrentSessionKey);
    }

    public static void CloseSessionFactory()
    {
        if(sessionFactory != null)
        {
            sessionFactory.Close();
        }
    }
} 

どのオプションが優先されますか?

なぜ(注射以外に)?

オプションを使用する場合A、構成はどこに配置しますISessionFactoryか?

ASP.NET MVCプロジェクトのどこかに配置する必要がありますか?どのように?

モンスターの質問を読んでくれてありがとう!ご指導よろしくお願いします!

4

4 に答える 4

2

mvc を使用して依存関係を注入する方法は、バージョンによって多少異なりますが、実際の依存性注入 (DI) コンテナーを使用すると常に役立ちます。ただし、このソリューションでは、ISessionFactory ではなく ISession をリポジトリに挿入する必要があります。これにより、DI コンテナーはセッションの有効期間を適切に管理できます。

Asp.Net MVC 3 を使用していて、特定の DI コンテナーへのアタッチメントがまだないと仮定すると、Nugetコンソールを起動して次のように入力します。

install-package Ninject.MVC3

これにより、Ninject (DI コンテナー) がダウンロードされ、それを使用するように mvc アプリケーションが構成されます。また、ファイル ~/App_Start/NinjectMVC3.cs も作成されます。これは、依存関係を構成する場所です。

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<ISessionFactory>()
        .ToMethod(c => new Configuration().Configure().BuildSessionFactory())
        .InSingletonScope();

    kernel.Bind<ISession>()
        .ToMethod((ctx) => ctx.Kernel.Get<ISessionFactory>().OpenSession())
        .InRequestScope();

    kernel.Bind<IRepository<>>().To<Repository<>>();        
}   

最初のステートメントは、何かが ISessionFactory を必要とする場合、NHibernate を遅延して初期化し、それを作成する必要があることを ninject に伝えます。このセッション ファクトリは、アプリケーションの存続期間中、アプリケーション全体のシングルトンとして保持されます。

2 番目のステートメントは、何かが ISession を必要とする場合、ISessionFactory のインスタンスを取得して OpenSession() を呼び出す必要があることを ninject に指示します。このセッションは、リクエストの範囲内で再利用され、リクエストの最後に破棄されます。

3 番目のステートメントは、ninject に、何らかのタイプの IRepository が必要な場合は、組み込みのロジックを使用して依存関係を解決するだけで新しいものを作成する必要があることを伝えます。

ここから、次のようにコードを書くことができ、すべてがうまくいくはずです。

public class WidgetController : Controller
{
    private readonly IRepository<Widget> _repository;
    public WidgetController(IRepository<Widget> repository)
    {
        _repository = repository;
    }
}

リポジトリに関しては、優れたブログ投稿を紹介したいと思います リポジトリは新しいシングルトンです

于 2012-01-24T20:59:15.900 に答える
1

Web アプリでは、Web リクエストごとにパターン NH セッションを使用する必要があります。Web リクエストごとにセッションを 1 つだけ持つ必要があり、リポジトリはこの単一のセッションを使用する必要があると思います。これを実装するには、セッションを開き、トランザクションを開始し、リクエストの開始時にセッションをアンビエント (現在の) セッションとしてバインドし、トランザクションを終了し、リクエストの終了時にセッションを閉じる IHttpModule を記述する必要があります。current_session_context_class を「web」に設定する必要もあります。次に、リポジトリ/DAO は次のようになります

    public TEntity Get(object id)
    {
        return sessionFactory.GetCurrentSession().Get<TEntity>(id);
    }
于 2012-01-24T14:13:53.730 に答える
0

MVC と NHibernate の最適なパターンは、リクエストごとのセッションです。
手順:

  1. Global.asax に public static ISessionFactory SessionFactoryを追加します。
  2. Application_Start()で、セッション ファクトリを構成および構築します。

    var config = new Configuration().Configure();
    SessionFactory = config.BuildSessionFactory();

  3. Application_BeginRequestでセッションを開き、CurrentSessionContext にバインドします。

    var nhSession = SessionFactory.OpenSession();
    CurrentSessionContext.Bind(セッション);

  4. Application_EndRequest()で、セッションのバインドを解除して破棄します

これで、コントローラーで、以下を呼び出してセッションにアクセスできます。

Global.SessionFactory.GetCurrentSession();

編集: @hival コメントに続いて

コントローラー内では、using ブロックでモデルを処理し、ロジックに基づいてコミット/ロールバックを実行します。

于 2012-01-24T14:43:54.273 に答える