19

たくさんの記事を読んだ後でも、リポジトリとやり取りするときの Unit of Work パターンの責任についてまだ確信が持てません。

リポジトリは集約ルート エンティティの読み込みと保存を担当するため、次のコード例を検討してください。

using(IUnitOfWork uow = container.CreateUnitOfWork())
{
     Repository<ARoot> roots = container.GetRepository<ARoot>();
     ARoot root = root.FindByName("ARoot");
     root.Name = "ANewName";

     roots.Save(root);
     uow.Commit();
}

作業単位インターフェースは、次のメソッドで定義されます。

public interface IUnitOfWork
{
     void Insert(object);
     void Update(object);        
     void Delete(object);
     void Commit();
     void Rollback();
}

リポジトリが非常に単純な SQL マッパーを使用して実装されているとします。そのため、FindByName には ARoot を返すための直接的な SQL が含まれています。Save の実装は次のようになります。

public void Save(T entity)
{
      IUnitOfWork uow = GetUnitOfWork();
      // Tell the UOW we are updating this entity
      uow.Update(entity);
}

Unit Of Work Commit コードは、エンティティを DB にマップするために必要なすべての SQL を構築しますか?

質問2)

集約ルートを作業単位に追加する場合、作業単位はルートとその子エンティティを永続化する責任がありますか?それともリポジトリの Save メソッドで変更されたエンティティを作業単位に追加する必要がありますか? 例えば

public void Save(T entity)
{
      IUnitOfWork uow = GetUnitOfWork();
      // Tell the UOW we are updating this entity
      uow.Update(entity);
      uow.Update(entity.AChildObject);
}

または...代わりに

作業ユニットは集約ルートのみを処理し、コミット時に変更セット内の各オブジェクトのリポジトリ Save メソッドを呼び出し、SQL マッピング コードを保持してリポジトリ内のエンティティを永続化し、最初のコード例を次のように変更しますか?

using(IUnitOfWork uow = container.CreateUnitOfWork())
{
     Repository<ARoot> roots = container.GetRepository<ARoot>();
     ARoot root = root.FindByName("ARoot");
     root.Name = "ANewName";

     //roots.Save(root);
     uow.Update(root);
     // and commit
     uow.Commit();
}

ありがとう、

ジェームズ

4

3 に答える 3

4

このプロジェクトでは、リポジトリを使用してエンティティのコレクションのように動作させ、UnitOfWork を使用してこれらのエンティティの変更を追跡し、それらをデータ ストアに書き戻します。

LinqToSql またはその他の OR Mapper を使用している場合、それ自体で UnitOfWork パターンを実装する可能性が高いため、多くの場合、独自の IUnitOfWork で ORMapper インスタンスのみを使用します。

私たちのリポジトリインターフェースは通常、次のようなものです..

  IEnumerable<Order> FindByCustomerId(string customerId);
  void Add(Order order);
  void Remove(Order order);

リポジトリに save メソッドはありません。UnitOfWork が必要ない場合、Add/Remove メソッドはデータストアに直接作用します。

UnitOfWork が必要な場合、パブリック インターフェイスは次のようになります...

void Commit();
void Rollback();

リポジトリには UnitOfWork との内部インターフェイスがあるため、リポジトリにクエリを実行すると、返されたオブジェクトの変更が UnitOfWork によって追跡されます。commit メソッドは変更をデータストアに書き戻します。rollback メソッドは単純にその変更をクリアします。

LinqToSql を使用すると、DataContext が変更追跡を処理し、Rollback では新しい Context をインスタンス化するだけです。永続性は、ルートとその子全体で処理されます。1 つの UnitOfWork インスタンスがすべてのリポジトリ間で共有されます。

LinqToSql を使用しない場合は、独自の UnitOfWork を実装します。これは Web サービスなどを呼び出す可能性があります。この場合、EntityBase クラスを使用してエンティティ クラス自体で変更追跡を行います。

ルートごとにリポジトリがありますが、1 つのルートの子がルート自体として使用されることがあります。そのため、多くの場合、OrderLineRepository のようなものが必要になります。これは、ユーザーが注文明細を検索したい場合にシステムにユースケースがあるためです。

于 2010-02-01T11:18:06.253 に答える
3

通常、私がそれを行うのが好きな方法は、IRepository.Save() を直接呼び出すことによって保存される変更を UoW が追跡することです。

また、UoW コードは、ドメインとの相互作用の外部で、アスペクトとして処理されることを好みます。これは、リクエストの完了の一部として、一部のグローバル コマンド ハンドラまたは Web サービス コードによって処理されることを意味します。つまり、リクエストを開始すると作業単位が開き、終了すると閉じます。このようにして、ドメインは UoW とその実装を認識できなくなります。

作業単位をコミットすると、.Save() およびその他の変更メソッドを呼び出すことによって行われた変更が永続化されます。おそらく、UoW が何らかの形でこれらの変更を追跡しているものです。

于 2011-06-25T23:58:45.190 に答える
2
  • UnitOfWorkはトランザクションハンドラーです
  • リポジトリは、オブジェクトをデータストアにロード/保存するための実際の作業を行っています

私は次のような定義を使用します:

IUnitOfWork { Commit(); }
IRepository { GetAll(); GetById(); Add(T item); Remove(T item); }

UnitOfWorkでSQLを作成する必要はありません。そのロジックは、リポジトリにあります。どのデータストアを使用していますか?

于 2011-06-29T09:07:10.610 に答える