46

(注:私の質問は、3か月前にこの質問をした人と非常によく似た懸念を持っていますが、回答されませんでした。)

私は最近MVC3+Entity Frameworkの使用を開始しましたが、ベストプラクティスは、リポジトリパターンを使用してDALへのアクセスを一元化することであると読み続けています。これには、DALをドメイン、特にビューレイヤーから分離しておく必要があるという説明も含まれています。しかし、私が見た例では、リポジトリは単にDALエンティティを返しています(またはそうであるように見えます)。つまり、私の場合、リポジトリはEFエンティティを返します。

だから私の質問は、それがDALエンティティのみを返す場合、リポジトリは何が良いのかということです。これにより、レイヤー間でDALエンティティを渡す問題が解消されない複雑なレイヤーが追加されませんか?リポジトリパターンが「DALへの単一のエントリポイント」を作成する場合、それはコンテキストオブジェクトとどのように異なりますか?リポジトリがDALオブジェクトを取得して永続化するメカニズムを提供する場合、それはコンテキストオブジェクトとどのように異なりますか?

また、データコンテキストオブジェクトを管理するために作業ユニットパターンがリポジトリアクセスを一元化することを少なくとも1つの場所で読みましたが、これがなぜ重要なのかについても理解していません。

私はここで何かが欠けていると98.8%確信していますが、私の読書からはそれを見ませんでした。もちろん、私は正しい情報源を読んでいないかもしれません...:\

4

7 に答える 7

59

「リポジトリ」という用語は、マーティン・ファウラーの著書「エンタープライズアプリケーションアーキテクチャのパターン」で「リポジトリパターン」が説明されている方法で一般的に考えられていると思います。

リポジトリは、ドメインとデータマッピングレイヤーの間を仲介し、メモリ内のドメインオブジェクトコレクションのように機能します。クライアントオブジェクトは、宣言的にクエリ仕様を作成し、満足のためにリポジトリに送信します。オブジェクトは、オブジェクトの単純なコレクションからの場合と同様に、リポジトリに追加したり、リポジトリから削除したりできます。リポジトリによってカプセル化されたマッピングコードは、バックグラウンドで適切な操作を実行します。

表面的には、Entity Frameworkはこれらすべてを実現し、リポジトリの単純な形式として使用できます。ただし、リポジトリには、単なるデータ層の抽象化以上のものが存在する可能性があります。

EricEvansによる「 DomainDrivenDesign」という本によると、リポジトリには次の利点があります。

  • 永続オブジェクトを取得し、ライフサイクルを管理するための単純なモデルをクライアントに提示します
  • これらは、アプリケーションとドメインの設計を永続化テクノロジー、複数のデータベース戦略、さらには複数のデータソースから切り離します。
  • オブジェクトアクセスに関する設計上の決定を伝達します
  • これらは、単体テスト(通常はメモリ内のコレクションを使用)のために、ダミーの実装を簡単に置き換えることができます。

最初のポイントは上記の段落とほぼ同じであり、EntityFramework自体がそれを簡単に実現できることは容易に理解できます。

EFが2番目のポイントも達成すると主張する人もいます。ただし、通常、EFは、各データベーステーブルをEFエンティティに変換し、それをUIに渡すために使用されます。データアクセスのメカニズムを抽象化している可能性がありますが、舞台裏でリレーショナルデータ構造を抽象化することはほとんどありません。

主にデータ指向の単純なアプリケーションでは、これは重要なポイントではないように思われるかもしれません。しかし、アプリケーションのドメインルール/ビジネスロジックがより複雑になるにつれて、よりオブジェクト指向になりたいと思うかもしれません。データのリレーショナル構造に、ビジネスドメインにとって重要ではないが、データストレージの副作用である特異性が含まれていることは珍しくありません。このような場合、永続性メカニズムを抽象化するだけでなく、データ構造自体の性質も抽象化するだけで十分ではありません。EFだけでは一般的にそれを行うのに役立ちませんが、リポジトリ層は役立ちます。

3番目の利点については、EFは(DDDの観点から)何もしません。通常、DDDはリポジトリを使用して、データの永続性のメカニズムを抽象化するだけでなく、特定のデータにアクセスする方法に関する制約を提供します。

また、トラバーサルで検索する方が便利な永続オブジェクトのクエリアクセスも必要ありません。たとえば、PersonオブジェクトからPersonのアドレスを要求できます。そして最も重要なのは、AGGREGATEの内部にあるオブジェクトは、ルートからのトラバーサルを除いてアクセスが禁止されていることです。

つまり、データベースにAddressテーブルがあるという理由だけで、「AddressRepository」はありません。デザインがこの方法でAddressオブジェクトにアクセスする方法を管理することを選択した場合、PersonRepositoryは、デザインの選択を定義および適用する場所です。

また、DDDリポジトリは通常、ドメインデータのセットに関連する特定のビジネスコンセプトがカプセル化されている場所です。OrderRepositoryには、Ordersの特定のサブセットを返すOutstandingOrdersForAccountというメソッドが含まれる場合があります。または、CustomerリポジトリにPreferredCustomerByPostalCodeメソッドが含まれている場合があります。

Entity FrameworkのDataContextクラスは、リポジトリ抽象化レイヤーが追加されていないと、このような機能には適していません。これらは、DDDが仕様と呼ぶものに対して適切に機能します。これは、式に対してデータを評価し、一致を返す単純なメソッドに送信される単純なブール式である可能性があります。

4番目の利点については、データコンテキストの代わりに使用できる戦略があると確信していますが、リポジトリにラップすると非常に簡単になります。

「作業単位」に関して、DDDの本は次のように述べています。

トランザクション制御はクライアントに任せます。REPOSITORYはデータベースに挿入およびデータベースから削除しますが、通常は何もコミットしません。たとえば、保存後にコミットしたくなりますが、クライアントにはおそらく、作業単位を正しく開始してコミットするためのコンテキストがあります。REPOSITORYが手を離すと、トランザクション管理が簡単になります。

于 2012-11-02T04:04:21.380 に答える
25

Entity Frameworkは、基本的にリポジトリ(および作業単位DbContext)に似ています。単純なシナリオでは、必ずしもそれを抽象化する必要はありません。

リポジトリの主な利点は、ドメインが無知であり、永続化メカニズムから独立している可能性があることです。レイヤーベースのアーキテクチャでは、依存関係はUIレイヤーからドメイン(または通常はビジネスロジックレイヤーと呼ばれます)を経由してデータアクセスレイヤーに到達します。これは、UIがBLLに依存し、BLL自体がDALに依存することを意味します。

より近代的なアーキテクチャ(ドメイン駆動設計やその他のオブジェクト指向アプローチによって伝播される)では、ドメインに外向きの依存関係があってはなりません。これは、UI、永続性メカニズム、およびその他すべてがドメインに依存する必要があり、その逆ではないことを意味します。

リポジトリは、ドメイン内のインターフェースを介して表されますが、永続化モジュール内のドメイン外で具体的な実装があります。このように、ドメインは抽象的なインターフェースのみに依存し、具体的な実装には依存しません。

これは基本的に、アーキテクチャレベルでのオブジェクト指向と手続き型プログラミングの違いです。

ポートとアダプタ、別名ヘキサゴナルアーキテクチャも参照してください。

リポジトリのもう1つの利点は、さまざまなデータソースへの同様のアクセスメカニズムを作成できることです。データベースだけでなく、クラウドベースのストア、外部API、サードパーティアプリケーションなどにも使用できます。

于 2012-11-01T15:47:12.330 に答える
6

そうです、これらの単純なケースでは、リポジトリはDAOの単なる別名であり、EFを別のデータアクセス技術に切り替えることができるという事実という1つの価値しかもたらしません。今日はMSSQLを使用していますが、明日はクラウドストレージが必要になります。または、EFの代わりにマイクロオームを使用するか、MSSQLからMySqlに切り替えます。

これらすべての場合において、アプリの残りの部分は現在使用しているストレージを気にしないため、リポジトリを使用することをお勧めします。

複数のソース(db +ファイルシステム)から情報を取得するという限られたケースもあります。リポジトリはファサードとして機能しますが、それでもDAOの別名です。

「実際の」リポジトリは、ドメイン/ビジネスオブジェクトを処理している場合にのみ有効です。ストレージを変更しないデータ中心のアプリの場合、ORMだけで十分です。

于 2012-11-01T15:56:32.097 に答える
2

複数のデータソースがあり、一貫したコーディング戦略を使用してそれらにアクセスしたい場合に役立ちます。

たとえば、複数のEFデータモデルがあり、一部のデータはストアドプロシージャを備えた従来のADO.NETを使用してアクセスされ、一部のデータはサードパーティAPIを使用してアクセスされ、一部はWindowsNT4サーバー上にあるAccessデータベースからアクセスされます。ほうきクローゼット内のほこりの毛布。

ビジネスレイヤーやフロントエンドレイヤーがデータの送信元を気にしないようにする場合は、「Entity Frameworkデータ」にアクセスするのではなく、「データ」にアクセスするための汎用リポジトリパターンを構築します。

このシナリオでは、実際のリポジトリの実装は互いに異なりますが、それらを呼び出すコードは違いを認識しません。

于 2012-11-01T15:52:43.117 に答える
2

あなたのシナリオを考えると、データレイヤーから返される必要のあるデータ構造(ドメインモデル)を表す一連のインターフェイスを選択するだけです。その場合、実装はEF、Raw ADO.Net、またはその他のタイプのデータストア/プロバイダーを組み合わせて行うことができます。ここでの重要な戦略は、実装が直接のコンシューマーであるドメインレイヤーから抽象化されることです。これは、ドメインオブジェクトの単体テストを行い、あまり一般的ではない状況で、データプロバイダー/データベースプラットフォームを完全に変更する場合に役立ちます。

まだ行っていない場合は、IOCコンテナーの使用を検討する必要があります。これにより、依存性注入によるソリューションの緩い結合が非常に簡単になります。 利用できるものはたくさんありますが、個人的にはNinjectが好きです。

ドメインレイヤーは、すべてのビジネスロジック(問題のドメインのルールと要件)をカプセル化する必要があり、MVC3Webアプリケーションで直接使用できます特定の状況では、ドメインレイヤーの上にあるサービスレイヤーを導入することは理にかなっていますが、これは必ずしも必要ではなく、単純なWebアプリケーションにとってはやり過ぎになる可能性があります。

于 2012-11-01T16:16:07.393 に答える
1

考慮すべきもう1つのことは、単一のデータストアで作業することがわかっている場合でも、リポジトリの抽象化を作成することは理にかなっている可能性があるということです。その理由は、アプリケーションが必要とする機能があり、ORM du jourのパフォーマンスが悪い(パフォーマンス)か、まったくないか、ORMをニーズに合わせて曲げる方法がわからないためです。

よく考えられたリポジトリインターフェイスの背後にORMをラップしている場合は、適切と思われるさまざまなテクノロジを簡単に切り替えることができます。私のリポジトリでは、一部のメソッドが作業にEFを使用し、他のメソッドがPetaPocoや(gasp)ADO.netコードなどを使用するのを見るのは珍しいことではありません。リポジトリの抽象化により、これらの複雑さをクライアントコードに漏らすことなく、手元のジョブにぴったりのツールを使用できます。

于 2013-03-29T20:11:48.390 に答える
0

多くの記事が「リポジトリ」と呼んでいるものについては、大きな誤解があると思います。そしてそれが、それらの抽象化がもたらす真の価値について疑問がある理由です。

私の意見では、純粋な形式のリポジトリはIEnumerableですが、あなたや多くの記事は「データアクセスサービス」について語っています。

私はここでそれについてブログを書きました。

于 2014-02-17T17:40:19.187 に答える