6

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 メソッドの開始時に同じ作業単位を再度開く手段が必要になると思います。

ビジネスレイヤー内で作業ユニットとリポジトリを使用する正しい方法は何ですか?

4

2 に答える 2

1

あなたがほとんどそれを持っているように私には見えます。新しいサーバースタックには、次の設定があります。

WCF Service Layer  --> just returns results from my Business Layer

My business layer is called, creates a unitofwork, creates the respository
Calls the respository function
Uses AutoMapper to move returned results into a DTO

My repository gets the query results and populates a composite object.

あなたがそこに持っているもののように見えます。Unityを使用して、ビジネスレイヤーと呼ばれるものを見つけますが。(私たちはそれを私たちの関数プロセッサと呼んでいます)

ただし、私が強くお勧めするのは、UnitOfWorkをクラスレベルに維持しないことです。結局のところ、各descreet機能は作業の単位です。だから私のものはこのようなものです(無実を保護するために名前が変更されました):

        using ( UnitOfWorkScope scope = new UnitOfWorkScope( TransactionMode.Default ) )
        {
            ProcessRepository repository = new ProcessRepository(  );
            CompositionResultSet result = repository.Get( key );
            scope.Commit( );

            MapData( );
            return AutoMapper.Mapper.Map<ProcessSetDTO>( result );
        }

また、scope.Commitをいつ実行するかについても長い議論がありました。これはクエリには必要ありませんが、アプリケーション層のすべての関数に一貫したパターンを確立します。ところで、リポジトリ/ユニットオブワークパターンにNCommonを使用しており、UoWをリポジトリに渡す必要はありません。

于 2012-06-29T21:19:01.723 に答える
0

IUnitOfWork 実装には、すべてのリポジトリが含まれています。

IUnitOfWork は、mvc コントローラーのようなプレゼンテーション レイヤーに挿入されます。

IUnitOfWork は mvc コントローラーに挿入されます。

IRepository は UnitOfWork 実装に注入されます。

于 2013-03-10T16:55:15.477 に答える