20

私はリポジトリを構築していますが、多くの場所で IQueryable をリポジトリ外に公開しない理由が 2 つあります。

1) 1 つ目は、さまざまな LINQ プロバイダーが異なる動作をする可能性があり、この違いはリポジトリ内に含まれている必要があるためです。

2) 2 つ目は、サービス レベルの開発者がデータベース クエリを変更して、誤ってパフォーマンスの問題を引き起こすことを防止することです。

問題2は、すべてのクエリロジックをリポジトリ内に保持し、外部クエリの構築を許可しないことによってのみ防止できると思いますか? しかし、それは私には少し非現実的なようです。

問題 1 は、データ オブジェクト パターンを使用することで解決されるようです。

例えばpublic IEnumerable<T> FindBy(Query query)

私の質問は、プロバイダーに依存しないラムダ式を渡すだけでなく、クエリオブジェクトと同じ機能と同じレベルの分離を提供するように見えるのはなぜですか?

例えばpublic IEnumerable<T> FindBy(Expression<Func<T,bool>> predicate)

これをしない理由はありますか?それはいくつかの規則に違反していますか?ベストプラクティス?私が知っておくべきことは何ですか?

4

1 に答える 1

24

を返すだけIQueryable<T>です。

別の「リポジトリ コード」を作成する前に、Ayende の記事Architecting in the Pit of Doom - The Evils of the Repository Abstraction Layerを読むことで大きなメリットが得られます。

あなたのアプローチは、間違いなく、不必要な複雑さを大幅に追加しています。

Generic List of OrderBy Lambdaの他の質問のすべてのコードは、既存の有効な API を不必要で見慣れない抽象化でマスクする以外に何もしていません。

お二人の懸念事項について、

  1. LINQ プロバイダーの動作は異なりますが、渡す述語を LINQ プロバイダーで処理できる限り、これは関係ありません。そうしないと、最終的にExpressionに渡される を渡しているため、同じ問題が引き続き発生します。実装が述語を処理できないIQueryable場合、述語を処理できません。(翻訳できないさらなるフィルタリングの前に評価する必要がある場合はIQueryProvider、いつでも a を呼び出すことができます)。ToList()

  2. クエリを変更するとパフォーマンスの問題が発生する可能性がありますが、必要な機能が公開される可能性が高くなります。さらに、最適化されていない LINQ クエリによって発生するパフォーマンスの問題は、データ アクセス ロジックの露出を避けるために必要以上に多くのレコードを取得しIQueryableたり、肥大化したデータ アクセス ロジックを体系的にフィルタリングしたりすることによって発生するパフォーマンスの問題よりも、悪影響が少ない可能性があります。実際には何もしない抽象化のレベル (最初の脅威はより重大です)。一般に、ほとんどの主要な LINQ プロバイダーは変換プロセスでクエリ ロジックを最適化するため、これは問題になりません。

クエリ ロジックをフロント エンドから隠したい場合は、汎用リポジトリを作成しないでください。実際のビジネス固有のメソッドでクエリをカプセル化します。さて、私は間違っているかもしれませんが、リポジトリ パターンの使用はドメイン駆動設計に触発されていると想定しています。この場合、リポジトリを使用する理由は、ドメイン モデルに重点を置いて永続性を無視したドメインを作成できるようにするためです。ただし、この種の汎用リポジトリを使用しても、セマンティクスが からCreate Read Update Deleteに変更されるだけFind Add Remove Saveです。そこに組み込まれている実際のビジネス知識はありません。

の意味 (および使いやすさ) を考慮してください。

interface IPersonRepository 
{ 
     Person GetById(int id);
     IEnumerable<Person> FindByName(string firstName, string lastName);
}

とは対照的に

interface IRepository<T> { 
     IEnumerable<T> FindBy(Query<T> query);
}

IRepository<T>さらに、 ( ではなく)を使用する利点を実際に指摘できますIQueryable<T>か?

また、一般的なアプローチでは、実際にはクエリ ロジックをまったくカプセル化していないことを考慮してください。外部でビルドすることになり、不要なコードがさらに増えることになります。

* を使用しないようにアドバイスするリソースに関するもう 1 つの注意事項IQueryable<T>は、その発行日を確認する価値があるということです。LINQ プロバイダーの可用性がかなり制限されていた時期がありました (初期の EF および LINQ-to-SQL まで)。その時点で を公開するIQueryable<T>と、Microsoft ORM のより一般的な代替手段の一部との非互換性が伴います (LINQ-to-NHibernate はかなり前に実装されています)。現時点では、本格的な ORM .NET ライブラリでは LINQ サポートが事実上どこにでもあります。

于 2012-08-16T03:20:54.527 に答える