Unit of Work/Repository パターンを使用して小さなアプリケーションを構築したので、ビジネス レイヤー内でこれを適切に使用する方法を理解するのに苦労しています。私のアプリケーションには、NHibernate または Entity Framework のデータ アクセス レイヤーがあります。これらを簡単に切り替えることができます。
Customer、Order など、多数のリポジトリがあります。私の作業単位は、テストする DAL に応じて、ISession またはオブジェクト コンテキストのいずれかになります。
私のビジネス層には、CreateOrder() という 1 つのビジネス メソッドが含まれています。私が理解するのに苦労しているのは、ビジネス層のどこで作業単位とリポジトリを初期化する必要があるかということです。
Nhibernate に注目すると、私の DAL は次のようになります。
public class NHibernateDAL : IUnitOfWork
{
log4net.ILog log = log4net.LogManager.GetLogger(typeof(NHibernateDAL));
ISession context;
public NHibernateDAL()
{
context = SessionProvider.OpenSession();
this.Context.BeginTransaction();
CurrentSessionContext.Bind(context);
}
public ISession Context
{
get { return context; }
}
public void Commit()
{
this.Context.Transaction.Commit();
context.Close();
}
public void Dispose()
{
ISession session = CurrentSessionContext.Unbind(SessionProvider.SessionFactory);
session.Close();
}
}
ビジネス層内で、作業単位とリポジトリを宣言する場所を知りたいです。それらはクラス レベルまたは CreateOrder メソッド内で宣言されていますか?
例えば:
public class BusinessLogic
{
UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
NhRepository<Order> _orderRepository = new NhRepository<Order>(_unitOfWork);
NhRepository<Customer> _customerRepository = new NhRepository<Customer>(_unitOfWork);
....
public void CreateOrder(.....)
{
Order order = new Order();
_orderRepository.Add(order);
_unitOfWork.Commit();
}
}
上記のコードは、CreateOrder() メソッドが初めて呼び出されたときにのみ機能しますが、セッションが閉じられているため、それ以降の呼び出しでは機能しません。トランザクションのコミット後に「context.Close()」呼び出しを削除しようとしましたが、これも失敗します。上記のアプローチは機能しませんが、このスコープでリポジトリと作業単位を宣言する方が正しいように思えます。
ただし、代わりに以下のように実装すると問題なく動作しますが、メソッド自体のスコープ内でリポジトリと作業単位を宣言するのは不自然に思えます。ビジネスメソッドが大量にある場合、リポジトリと作業単位をいたるところに宣言することになります。
public class BusinessLogic
{
public void CreateOrder(.....)
{
UnitOfWork _unitOfWork = new UnitOfWork(NHibernateDAL);
var _orderRepository = new NhRepository<Order>(_unitOfWork);
NhRepository<Customer> _customerRepository = null;
Order order = new Order();
_orderRepository.Add(order);
_unitOfWork.Commit();
}
}
これをクラス レベルの宣言で実装する場合、CreateOrder メソッドの開始時に同じ作業単位を再度開く手段が必要になると思います。
ビジネスレイヤー内で作業ユニットとリポジトリを使用する正しい方法は何ですか?