2010-11-24 13 views
15

私は以下の実装を持っており、NHibernateをセッションとトランザクションに正しく使用するかどうかのフィードバックをしたいと思います。ここでNHibernateの作業単位パターンとNinjectの正しい使用

Bind<IUnitOfWork>().To<UnitOfWork>().InTransientScope(); 
Bind<ISessionFactory>().ToProvider<NHibernateSessionFactoryProvider>().InSingletonScope(); 
Bind<IRepository>().To<Repository>().InTransientScope(); 

を結合

public interface IUnitOfWork : IDisposable 
{ 
    ISession CurrentSession { get; } 
    void Commit(); 
    void Rollback(); 
} 

public class UnitOfWork : IUnitOfWork 
{ 
    private readonly ISessionFactory _sessionFactory; 
    private readonly ITransaction _transaction; 

    public UnitOfWork(ISessionFactory sessionFactory) 
    { 
     _sessionFactory = sessionFactory; 
     CurrentSession = _sessionFactory.OpenSession(); 
     _transaction = CurrentSession.BeginTransaction(); 
    } 

    public ISession CurrentSession { get; private set; } 

    public void Dispose() 
    { 
     CurrentSession.Close(); 
     CurrentSession = null; 
    } 

    public void Commit() 
    { 
     _transaction.Commit(); 
    } 

    public void Rollback() 
    { 
     if (_transaction.IsActive) _transaction.Rollback(); 
    } 
} 

Ninjectは使い方の例です:

私の以前の実装では
public class Repository : IRepository 
{ 
    private readonly ISessionFactory _sessionFactory; 

    public Repository(ISessionFactory sessionFactory) 
    { 
     _sessionFactory = sessionFactory; 
    } 

    public void Add(IObj obj) 
    { 
     using (var unitOfWork = new UnitOfWork(_sessionFactory)) 
     { 
      unitOfWork.CurrentSession.Save(obj); 
      unitOfWork.Commit(); 
     }   
    } 
} 

私はそう

public Repository(IUnitOfWork unitOfWork) 
    {... 
のように私のリポジトリコンストラクタにIUnitOfWorkを注入します

しかし、Dispose()メソッドは実行されず、この例外をスローするために後続の呼び出しが発生します。「破棄されたオブジェクトにアクセスできません。オブジェクト名: 'AdoTransaction'。 "

+3

あなたの最終的な決定は何でしたかわかりませんが、それをしないでください! :)真面目に、NHibernateはすでにかなりの抽象化とUoWパターンを追加しています。ちょうど箱からすぐにNHibernateを使用し、あなたのコードをシンプルに保つ。あなたは本当にデバッグするためにさらに抽象化したいですか? –

答えて

35

最初の観察:あなたのリポジトリは作業ユニットをコミットしてはいけません。これは作業ユニットのパターン全体を破ります。マイクロ管理 "NHibernateセッション

作業単位は、アプリケーション/サービス層で上位に参照する必要があります。これにより、潜在的に異なるリポジトリにいくつかのアクションを実行するアプリケーションコードを持つことができます。最後にすべてをコミットしてください。

UnitOfWorkクラス自体はOKですが、本当に必要かどうかを尋ねる必要があります。NHibernateでは、ISessiあなたの仕事の単位です。あなたのUnitOfWorkクラスは多くの価値を追加していないようです(とにかくCurrentSessionプロパティを公開しているからです)。

しかし、あなたはそれについて考える必要があります。私はあなたがこの点について間違っていると思います。セッションの有効期間の管理は、開発しているアプリケーションのタイプによって異なります.Webアプリケーションでは、通常、リクエストごとに作業単位が必要です(リクエストごとにセッションをnhibernateしたい場合があります)。デスクトップアプリケーションでは、やや複雑ですが、ほとんどの場合、「セッションごとのセッション」または「ビジネストランザクションごとの会話」が必要になります。

+0

フィードバックJeroenhに感謝します。私たちのアプリケーションは単純なcrud操作を実行するだけでよく、いくつかのアクションを実行したり、すべてを一度にコミットする必要はありません。 なぜ私はUnitOfWorkがオープニングセッションを抽象化し、変換を開始してセッションを閉じることを望んでいたからです。 –

+6

IUnitOfWorkの利点は、ORMへの結合が減少することです。または、少なくともそれが私が考えることができる唯一の利点です:) –

+5

@ Ryan Barettしかし、その使用は何ですか? http://ayende.com/Blog/archive/2010/07/30/the-false-myth-of-encapsulating-data-access-in-the-dal.aspx – jeroenh

8

私はほとんどCRUDタイプのアプリケーションを持っていますが、私はリポジトリパターンで作業単位を実装しましたが、実際にはセッション/トランザクション分割から離れることはできませんでした。セッションとトランザクションには異なる生涯が必要です。デスクトップの世界では、セッションは通常「画面ごと」で、トランザクションは「ユーザーごとのアクション」です。

この詳細情報はexcellent articleです。私がなってしまったので、何

だった: - >ラップセッション、IDisposable

  • IAtomicUnitOfWorkを実装 -

    • IUnitOfWork、>は、トランザクションをラップ実装IDisposable
    • IRepository - >提供を取得、保存、削除し、クエリアクセス

    が必要ですを作成してIAtomicUnitOfWorkを作成し、IRepositoryを構築するにはIAtomicUnitOfWorkが必要です。これにより、適切なトランザクション管理が行われます。それは私自身のインターフェースを実装することで得られたものです。

    jeroenhは言ったように、ISessionITransactionを使用するのはほぼ同じですが、最終的に私が定義したインターフェイスに対してすべてのコードを書いたほうが少し良いと感じました。

  • +0

    IUoWをIRepositoryに送付することをお勧めします。概念的な分割:IUoWは、定義上、トランザクションです。セッションのコンセプトは少し違っています(IDatabaseGenericSessionと呼ぶ)別の名前が必要です。 –

    +0

    @ Ryan Barrett:セッションラッパーのより良い名前は、「コンテキスト"私は、ObjectContextはすでに.NETで撮影されていると思いますが、そうではありませんか?たぶんEntityContext? –

    3

    答えの重要な部分は、トランザクションサイズをどのようにしたいかにあります。今すぐ(jeroenhが示したように)、トランザクションはリポジトリのメソッド呼び出しごとに行われます。これは非常に小さく、おそらく必要ではありません。私はASP.MVCアプリケーションを作成し、単一のhttp要求からすべてを含むトランザクションサイズを使用します。複数のデータベースの読み取り/更新が可能です。私はIOCのために同じ作業単位とNinjectを使用しています。多分何かがあなたの問題に役立つ、見てみましょう:

    http://bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/

    http://bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/

    http://bobcravens.com/2010/09/the-repository-pattern-part-2/

    http://bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/

    は、この情報がお役に立てば幸いです。

    ボブ

    +0

    リソースBobに感謝します。私のアプリケーションはMVCアプリケーションではありませんが、アイデアは同じです。 –

    +0

    こんにちはボブ、残念ながらあなたのブログはblog.bobcravens.comからbobcravens.comに変更されたURLを持っています。したがって、例えば画像へのリンクとして、多くが壊れています。あなたはそれを修正することができることを願っています。 –

    関連する問題