Generic Repository with EF 4.1ポイントは何ですか


145

DbContext、DbSet、および関連するインターフェースをさらに掘り下げているので、これらの実装の周りに別の「汎用」リポジトリを実装する必要があるのはなぜでしょうか。

DbContextとIDbSetが必要なすべてを行い、DbContext内に「作業単位」を含めるように見えます。

ここに何か欠けているのですか、それとも人々が理由なく別の依存関係の層を追加するのを楽しんでいるように見えますか?


これは少し異議あり/意見ベースの問題です。これについては、ここで説明しました
Amit Joshi

回答:


202

あなたは実際に正しいです。DbContextは作業単位パターンIDbSetの実装であり、リポジトリパターンの実装です。

リポジトリは現在非常に人気があり、使いすぎています。エンティティフレームワーク用のリポジトリの作成に関する記事が数十あるだけで誰もがそれらを使用しますが、実際にはこの決定に関連する課題については誰も説明していません。

通常、リポジトリを使用する主な理由は次のとおりです。

  • 上層からEFを隠す
  • コードをよりテストしやすくする

最初の理由は、ある種のアーキテクチャの純粋さと、上位層をEFから独立させると、後で他の永続化フレームワークに切り替えることができるという素晴らしいアイデアです。実世界でそのようなことを何回見ましたか?リポジトリはEFがデフォルトで許可するものをラップする多くの追加機能を公開する必要があるため、この理由によりEFでの作業ははるかに困難になります。

同時に、EFコードをラップすることで、コードをより適切に整理し、関心の分離ルールに従うことができます。私にとって、これはリポジトリと作業単位の唯一の真の利点になる可能性がありますが、EFでこのルールに従うと、コードのメンテナンス性と可読性が向上する可能性があることを理解する必要があります小規模なアプリケーションの場合、これは不必要に複雑になる可能性があります。

2番目の理由は部分的に正しいです。EFの大きな不利な点は、モック化が難しい堅固なアーキテクチャであるため、上位層をユニットテストする場合は、EFをラップして実装をモックできるようにする必要があります。しかし、これには、ここで説明した他の多くの結果があります

Ayendeのブログをフォローしています。NHibernateを使用したことがあれば、おそらく彼の記事を知っているでしょう。この男は最近、NHibernateでリポジトリを使用することに対していくつかの記事を書きましたが、NHibernateはモック可能です。


3
あなたはモックができIDbSet、あなたもあなたの派生コンテキストでカスタムインターフェイスを定義することができますが、すべてのthats。コードでChangeTracker、エントリ、その他を使用すると、それらをすべてラップするために多大な労力が必要になります。
Ladislav Mrnka、2011

1
はい、EFはパフォーマンス指向のツールではありません。少なくともMSには、将来のバージョンでこれを改善する多くの機会があります。
Ladislav Mrnka、2011

2
@chiccodoro:そうです。ただし、モックされたクラスが内部的にLinq-to-entitiesクエリに渡されるパラメーターとして公開IQueryableまたは受け入れるExpression<>と、単体テストではテストできない副作用を持つモックされたコンポーネントの外部にロジックを定義します。
Ladislav Mrnka、2011

8
ビジネスレイヤーでそのままDbSetとBdContextを使用している場合は、そことDataLayerプロジェクトでEntityFramework.dllを参照する必要があります。それだけで、ある種のラッピングが必要であることがわかります。
インゴヴァルス

2
downvote:incomplete-リポジトリインターフェースの背後でEFを抽象化すると、SLとWPFの両方でまったく同じクライアントコードを実行できます。
h.alex 2013

21

私も同じ問題に取り組んでいます。EFレイヤーの単体テストのモック機能は重要です。しかし、この素晴らしい記事に出くわし、派生したDbContextが汎用インターフェイスを実装し、DbSetではなくIDbSetを公開することを確認して、EF 4.1 DbContextをモック可能に設定する方法を説明しました。私はDatabase Firstアプローチを使用しているため、データベースが既に存在するため、派生したDbContextを生成するために使用するT4テンプレートを変更し、それを生成してIDbSetインターフェイスを返し、汎用インターフェイスから派生させました。そうすれば、全体を簡単にモック化でき、独自の作業単位やリポジトリパターンを実装する必要がなくなります。ジェネリックインターフェイスを使用するサービスコードを記述し、単体テストに進むと、

http://refactorthis.wordpress.com/2011/05/31/mock-faking-dbcontext-in-entity-framework-4-1-with-a-generic-repository/


5

リポジトリを作成する理由の1つは、EntityFrameworkから別のものに、またはその逆に移動する場合に、DBSetおよびDbContextの実装を非表示にすることができるようにするためです。

たとえば、NHibernateを使用していて、そのフレームワークへのすべての呼び出しをリポジトリクラス内にラップしました。彼らは取得が「汎用」になるためにIEnumerableを返し、私のリポジトリには標準のCRUD操作(更新、削除など)があります。Entity Frameworkに長い間移動しました。そうすることで、ViewModelクラス以降は何も変更する必要がありませんでした。それらはリポジトリを指しているため、リポジトリの内部を変更するだけで済みました。これにより、移行時の生活がはるかに簡単になりました。

(私はISeriesに接続しているため、NHibernateを使用しましたが、当時、ISeriesでEFを使用したコスト効果の高い実装はありませんでした。利用可能な唯一のものは、DB2ConnectのIBMに12,000ドルを支払うことでした)


「ほとんど」(DBSetとDbContextを非表示にすることについて)EFをコンシューマに公開する必要はありません(たとえば、DIを利用する場合)が、IDbSet <T>プロパティを公開するインターフェイスが必要か、さらに一歩進んで、すべてのプロパティをIQueryable <T>として入力しますが、私のポイントは、DbSetおよびDbContextへの依存を完全に隠すことができるということです。CRUD操作は拡張メソッドとして記述できます。異なるバッキングストア用に複数の拡張メソッドを記述できます。ただし、LINQの使用を非表示にすることはできません。
Shaun Wilson
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.