2

私は実パターンを使ったビジュアルスタジオソリューションを持っています。 IRepository(Crud実装)、IDbFactory(リポジトリで使用)、IUnitOfWorkがあります。私はまた、カスタムクエリーと複雑なデータベース操作を構築するためにリポジトリを使用するサービスを持っています。私はNinjectでIoCパターンも使用しています。 Web MVCコントローラでは、データベースにアクセスするためにサービスのみを使用します。 リポジトリは、EntityFrameworkコンテキストを作成するIDbFactoryを受け取ります。 私はいくつかの問題を抱えて:私はそれらの両方のGETALL()メソッドを呼び出して、2つのリポジトリを使用する必要がありますそれらを結合するための2つのテーブルにアクセスする必要があるときに、サービスでソリッドの原則、Asp Net MvcのリポジトリパターンとEntityFrameworkキャッシュ

  • を。この場合、両方のリポジトリは同じEntityFrameworkコンテキストを共有する必要があります。
  • 前のケースでは、すべてのリポジトリでDbContextを共有する必要があるため、異なるリポジトリのサービスでIQueryablesに参加することができます。
  • これを達成するために、私はIoCコンテナ内でシングルトンスコープのDbContextを設定しました。したがって、すべてのリポジトリは同じDbContextを共有します。
  • このソリューションの問題点は、DbContextにキャッシュがあることです。したがって、外部プロセス(Webプロジェクトとは異なる)が自分のデータを変更した場合、DbContextはそれを認識せず、Webプロジェクトは実際のデータを時々表示しません。
  • I読んほぼすべてのリポジトリの呼び出しでDbContextを破壊するが、すべてのリポジトリが同じDbContext

私のプロジェクト構造と間違って私が何かを使用する必要がありますので、私はこれを行うカント?これは私がリポジトリ層で修正する必要があるものですか?私は何をするのですか?プロジェクトは開発段階にあり、データアクセスアーキテクチャを変更することができます。私はコントローラーでIQueryablesを使用して、データグリッドのユーザーフィルターがSQLクエリーを生成するのが好きです。

+1

CodeReviewでは、これらの種類の質問に適したフォーラムを提供しています。例:http://codereview.stackexchange.com/questions/11785/ef-code-first-with-repository-unitofwork-and-dbcontextfactory –

+1

これは、IRepositoryを構築することは通常時間の無駄であるという古典的な例です。 EFはすでにリポジトリと作業単位を実装しており、dbを抽象化しているので、何を達成するために抽象化の別のレイヤーを削除しましたか?あるリポジトリに保存するまで待ってから、同じコンテキストにオブジェクトが添付されているため、別のリポジトリに変更を保存してください。あなたがウェブサイトやサービスのようなものであれば、要求ごとにDbContextの寿命を延ばすことができますが、IRepositoryは通常その価値よりも問題が多い、 – Mant101

+0

という別の問題は、あなたのDbContextがシングルトンだということです。これは、すべてのユーザーが同じDbContextを実行していることを意味します。 DBContext内の固有の作業単位を分割します。各作業単位に対して作成されたdbcontextが必要です。 – Fran

答えて

4

ここに記載された問題に関しては、プロジェクトの構造に問題はありません。この問題は、シングルトンスコープを使用することによってもたらされます。 Webアプリケーションの場合は、代わりにRequestスコープを使用する必要があります。これにより、要求ごとに新しいコンテキストを取得できるため、異なる要求や異なるクライアント間で重複することはなく、非常に危険です。

つまり、あなたのプロジェクト構造は過剰に設計されています。リポジトリ/作業単位パターンは、低レベルのデータアクセスを目的としています。 Entity Frameworkと同様に、ORMもそのすべてを処理します。実際、Entity Frameworkはすでにこれらのパターンを実装しています。 DbContextは作業単位であり、それぞれDbSetはリポジトリです。これに加えて独自のリポジトリ/作業単位のユニットを追加することは冗長で不要です。サービスでは、Entity Frameworkのコンテキストを直接利用する必要があります。それでも、複数のサービスを持つことは、彼らが何をするかによって、おそらく不必要なことです。それらがすべて同じデータソース(つまり、Entity Frameworkコンテキスト)で動作し、特にそれらがすべて同じ Entity Frameworkコンテキストで動作する場合、それらはすべて実際に1つにロールバックされるべきです。

個人的なプロジェクトでは、一意のコンテキストインスタンスごとに汎用メソッドを持つ単一の "サービス"クラスを使用します。ジェネリックメソッドは、 "サービス"クラスの追加インスタンスを新規に作成することなく、そのコンテキストに属するすべてのエンティティで動作させることができます。すべてが1つまたは複数のインタフェースを実装し、依存関係注入を使用してインタフェースの制約を満たすことを保証することによって、基礎となるデータレイヤが完全に取り除かれます。あなたが興味を持っているなら、私はseries of postsを持っています。

あなたはパターンや「ベストプラクティス」に集中しすぎているようですので、これをすべて言います。それらはちょうどガイドです。彼らは自転車の車輪のようなものです。それらはすべて優れたコード設計のさまざまな原則に基づいています。 の原則を学び、適用して、何らかの種類のデザインパターンのすべてのボックスをチェックすることについて心配する必要はありません。

スタックオーバーフローのコアコードベースは、生のパフォーマンスにレーザーを集中させ、適用されたときに実際にパフォーマンスを低下させるため、多くのパターン(依存性注入)を避けます。要点は、アプリケーションの設計方法は、特定のアプリケーションのニーズに基づいていることです。デザインパターンは、想定していると考えるだけでなく、アプリケーションのニーズに合わせて適用する必要があります。

+0

Entity FrameworkでUnitOfWork/Repositoryパターンをレイヤーする1つの理由エンティティフレームワークを他のコードから抽象化することです。これはいくつかの例で私を助けました。 エンティティフレームワークをアップグレードしたい場合、作業単位リポジトリを破損した変更がいくつかあったため、変更を一度行うことができ、残りのコードには問題はありませんでした。 また、DocumentDbにいくつかのエンティティを追加して、リポジトリに既存のリポジトリの動作を模倣することができました。残りのコードは、これらのアイテムの再取得時に基本的に同じように見えます。 – MikeS

+0

同じ結果を達成する他の方法があり、リポジトリ/作業単位は最悪です。私の答えで説明したように、私は* anything *で動作する単一の再利用可能なクラスを持ち、Entity Frameworkは完全に見えません。 –

+1

それが「最悪の方法」であることを説明してください。それは何年もの間、私のためにうまくいきました。作業単位を使用すると悪化する可能性はありませんか?おそらくそれが悪化することを夢見る方法はありませんか? – MikeS

0

まず、ビジネスユニット全体でDbContextのライフサイクルが終了する必要があります。これはMVCアプリケーションではHttpRequestごとに行われます。これは、ユーザーからの応答を受信する要求の送信の開始からトランザクションを提供します。

第2に、GetAll()機能をベースリポジトリに持つべきではありません。これは非常に間違った解決策であり、アプリケーションのパフォーマンスに影響を与える可能性があります。次のような関数を作成する必要があります。GetByQuery(Func<T, bool> whereQuery, int skip, int take)ここで、Tはエンティティクラスのジェネリック型です。または、ソート用のパラメータを追加することもできます。

おそらく、リポジトリパターンの辞退について考えるべきでしょうか?あなたのプロジェクトはどれくらいの大きさですか?将来的にデータストレージを変更する可能性はありますか?それ以外の場合は、サービスのDbContextで直接操作できます。 Entity Frameworkは、リポジトリパターンとUnitOfWorkの実装の一種です。

+0

彼のGetAll()がIQueryableを返す場合、EFは遅延実行を使用するため、述語を追加したり、テイクをスキップしたり、パフォーマンスペナルティなしで並べ替えることができます – Fran

+0

彼が話しているパフォーマンスのペナルティは、テーブルのすべてのレコードをロードしていると思います。何百万というレコードがある場合、これは非常にコストがかかる可能性があります。しかし、それはどのように使用されている。あなたが単純に制限を適用しないならば、 'GetByQuery'のようなものへの一般的なアクセスだけでも* all *レコードを得ることができます。 'GetAll'メソッドを持つこと自体は問題ではありません。責任を持って使用する必要があります。 –

+0

私はIQueryableについて言及しています。彼はGetByQueryの戻り値型については言及していません。GetByQueryはListでなくIQueryableである可能性があります。 Fran