3

私はUnitOfWorkとRepo Patternについてウェブ上で多く見ましたが、なぜ、どのように使用するのかはまだ分かりません。UnitOfWorkをリポジトリパターンとともに使用する理由は何ですか?

私はこの記事で提案されているようにDIを使ってIoCを使用してリポジトリをテスト可能にすることができると考えています。What are best practices for managing DataContext私はそうのようにそれを廃棄その後、私のリポジトリコンストラクタへの依存としてコンテキストを渡して検討している?:

public interface ICustomObjectContext : IDisposable {} 
public IRepository<T> // Not sure if I need to reference IDisposable here 
public IMyRepository : IRepository<MyRepository> {} 

public class MyRepository : IMyRepository 
{ 
    private readonly ICustomObjectContext _customObjectContext; 

    public MyRepository(ICustomObjectContext customObjectContext) 
    { 
     _customObjectContext = customObjectContext; 
    } 

    public void Dispose() 
    { 
     if (_customObjectContext != null) 
     { 
      _customObjectContext.Dispose(); 
     } 
    } 

    ... 

} 

リポジトリパターンとのUnitOfWorkを使用しての私の現在の理解を、複数のリポジトリ間で操作を実行することです - この動作は、@ Ladislav Mrnkaがウェブアプリケーションに対して推奨するものと矛盾するようです。

Webアプリケーションの場合、リクエストごとに単一のコンテキストを使用します。 Webサービスでは、コールごとに単一のコンテキストを使用します。 WinFormsまたはWPFアプリケーションでは、フォームまたはプレゼンターごとに単一のコンテキストを使用します。このアプローチを使用することを許さないいくつかの特別な要件がありますが、ほとんどの状況でこれで十分です。

は(だけでなく他の記事でこれを見た)私が正しく、彼を理解している場合のDataContextが要求またはプレゼンターごとに短命と使用されるべき完全な答えhere

を参照してください。この場合、スコープはそれを使用しているコンポーネントに限定されているため、リポジトリはコンテキストに対して操作を実行することが適切です。

私のリポジトリは一時的なものとしてIoCに登録されているので、リクエストごとに新しいリポジトリを取得する必要があります。それが正しいならば、私は各要求と共に新しい文脈(上のコードで)を得て、それを廃棄しなければならないと言いました... なぜ私はUnitOfWorkパターンをリポジトリパターンで使用しますか?上記の条約に従う?

+0

それだけあなたの質問に関連していない:

コードは次のようになります。しかし、あなたがこのクラスに依存関係として注入クラス内のオブジェクトを配置することは非常に悪に見えます。クラスはオブジェクトをインスタンス化することは明らかではないので、それを処理する責任はありません。 – Slauma

+0

ありがとう@Slaumaは、これに関するWouterの注記に注目しました。私はそれを修正する必要があります。 – Rich

答えて

6

作業単位パターンは、必ずしも複数のコンテキストをカバーするとは限りません。これは、トランザクションと同様に、単一の操作または作業単位をカプセル化します。

コンテキストを作成すると、基本的に作業ユニットが開始されます。 DbContext.SaveChanges()を呼び出して終了します。

現在の実装では、Entity FrameworkのDbContext/ObjectContextは、リポジトリパターンと作業単位パターンの両方に似ています。

+0

ありがとう@Dennis。 _DbContext/ObjectContextは、repoとUoWパターンの両方に似ています。私はUoW/Repos&Entityを研究していたので、これを見てきました。あなたの意見では、エンティティとのUoWは必要ではありませんか? – Rich

+0

@Rich私はパターンが必要であると言います。これは、ドメインドリブンデザインでは、データベース内の各テーブル(Contextを直接使用する場合に発生する)ではなく、各集約ルートに対してのみリポジトリを使用するためです。リポジトリを使用する場合、FindOrdersForCustomerのようなより具体的なメソッドを作成し、それらを1か所に実装することができます。 UoWとリポジトリパターンを使用するとDRY(繰り返しはしません)を使用し、すべてのデータアクセスロジックを1か所に保持します。 –

+0

いつものように、これは実際の要件によって異なります。しかし、文脈境界を越える必要がないかぎり(すでに言及したように、設計上の欠陥を示唆しているかもしれない)限り、組み込みのUoWをEFに入れたいと思っています。 –

2

1つのWebリクエストで同じコンテキストのインスタンスを共有するときに、コンテキストのSaveChangesをリポジトリから遠ざけたい場合は、単純化されたUoWを使用します。

_customObjectContext.SaveChanges()と似ているあなたのリポジトリにSave()メソッドがあると思います。次に、ビジネスロジックを含む2つのメソッドがあり、reposを使用してDBの変更を保持すると仮定します。わかりやすくするため、MethodAMethodBとします。これらの両方には、いくつかのアクティビティを実行するためのかなりの量のロジックが含まれています。 MethodAはシステムで別々に使用されますが、何らかの理由でMethodBでも呼び出されます。何が起こるかは、MethodAが変更をリポジトリに保存し、MethodAと呼ばれる前に同じ依頼変更がMethodBで行われているため、希望するかどうかにかかわらず保存されます。そのような場合には、意図せずにトランザクションをMethodBの中で中断し、コードを理解しにくくします。

私はこれを十分に明確に説明していただければ幸いです。とにかくそれ以外の理由で私はUoWがあなたのシナリオに役立つだろう理由を見ることができません。 Dennis Traubがかなり正確に指摘しているように、ObjectContextとDbContextは実際にはUoWの実装であるため、おそらくあなた自身でそれを実装しながらホイールを再開発するでしょう。

+0

デニスの答えはもっとも有益でした。あなたの答えに+1 - それは助けた。ありがとう@dmusial。 – Rich

1

ObjectContext/DbContextはUnitOfWorkパターンの実装です。いくつかの操作をカプセル化し、1つのトランザクションでデータベースに送信されることを確認します。

あなたがしている唯一のことは、コードの残りの部分の特定の実装に依存していないことを自分のクラスにラップすることです。

あなたの場合、問題はあなたのContextがあなたのRepositoryによって処分されるべきでないという事実にあります。 RepositoryContextをインスタンス化するものではないので、それを破棄してはいけません。複数のリポジトリをカプセル化するUnitOfWorkContextの作成と廃棄を担当し、UnitOfWorkではSaveメソッドを呼び出します。

using (IUnitOfWork unitOfWork = new UnitOfWork()) 
{ 
    PersonRepository personRepository = new PersonRepository(unitOfWork); 
    var person = personRepository.FindById(personId); 

    ProductRepository productRepository = new ProductRepository(unitOfWork); 
    var product= productRepository.FindById(productId); 

    p.CreateOrder(orderId, product); 
    personRepository.Save(); 
} 
+0

@Wouter ContextをTransient(城を使用)として登録すると、Contextを正しく処分することについて心配する必要はありませんか? – Rich

+0

@リッシュ申し訳ありません城を使用していませんが、UoWパターンの使い方をコードサンプルで掲載しました。 usingステートメントは、UoWがコンテキストを破棄していることを確認します(新しいUnitOfWork()は使用しませんが、DIを使用します) –

+0

他の誰かがこの回答とコメントに遭遇する場合に備えてください。コンテキストは、私が見てきた推奨事項に基づいてPerWebRequestライフスタイルに登録する必要があります。 – Rich

関連する問題