11

RavenDBプロジェクトにリポジトリとサービスパターンを実装するのにいくつかの問題があります。RavenDBではクエリにいくつかのインデックスを使用しているため、主な懸念事項はリポジトリインターフェイスがどのように見えるかです。

親IDが1に等しいすべてのアイテムをフェッチする必要があるとします。1つの方法は、IQueryable List()を使用してすべてのドキュメントを取得し、where句を追加して、親IDが1に等しいアイテムを選択することです。これは悪い考えのようです。 RavenDBではインデックス機能を使用できないためです。したがって、他のアプローチは、リポジトリにIEnumerable Find(string index、Func predicate)のようなものを含めることですが、これも十分にジェネリックではなく、RavenDBから変更する場合にこのメソッドを実装する必要があるため、悪い考えのようです。一般的なSQLサーバーに。

では、ジェネリックリポジトリを実装しながら、RavenDBのインデックスのメリットを享受するにはどうすればよいでしょうか。

4

4 に答える 4

10

まず、リポジトリパターンを使用する理由を尋ねます。

ドメイン駆動設計を行っているためにパターンを使用したい場合は、これらの回答のも​​う1つが指摘しているように、クエリの意図を再考し、ドメインの観点からそれについて話す必要があります。これを中心にモデル化を開始できます。

その場合、仕様はおそらくあなたの友人であり、あなたはそれらを調べる必要があります。


ただし、私の答えを続ける前に、質問の一部を少し見てみましょう。

十分に一般的ではなく、RavenDBから一般的なSQLサーバーに変更する場合に備えて、このメソッドを実装する必要があるため、悪い考えのように思われます。

あなたはそれを間違った方法で行っています-このレベルでシステムを完全に永続性にとらわれないようにしようとすると問題が発生します-クエリ自体からデータストアの固有の機能を隠そうとすると、なぜわざわざRavenDBを使用するのですか?

私が単純なドキュメント指向で使用する傾向がある方法(つまり、データに関して話しますが、これはあなたがしているように見えます)は、コマンドからクエリを分割することです。

なぜ親IDでドキュメントを照会したいのか、自問してみてください。ページにリストを表示するのですか?では、なぜこれをドキュメントの観点からモデル化しようとしているのですか?ビューモデルの観点からこれをモデル化し、RavenDBからこのデータを取得する最も効果的な方法を使用してみませんか?(インデックス(動的またはその他)に対するクエリ)、これを「いくつかの入力」を受け取り、「出力」を生成するファクトリに固定します。永続ストアを変更する場合は、これらのファクトリを変更できます。(ASP.NET MVCアプリケーションをさらに一歩進めて、シングルアクションコントローラーを使用しています。コントローラーとは呼ばず、ほとんどの場合、それらからクエリを実行します)。

ドキュメントを更新したり、ドキュメント全体でビジネスロジックを実行したりするために、実際にドキュメントを親IDで引き出したい場合は、モデルが間違っている可能性があります。通常、書き込み操作には、単一のドキュメントへの変更のみが含まれます。トランザクションの境界を中心にドキュメントをモデル化する必要があります。

TL; DR

実際に何を達成したいのか、なぜ「リポジトリパターン」または「サービスパターン」を使用したいのかを考えてください。これらの単語は、アプリケーションをモデル化した場合に最終的に発生する可能性のあるシナリオを説明する方法として存在します。ニーズは、特定のオブジェクトの役割を表現する一般的な方法としてではなく、すべての機能を強化するために必要なものとしてではありません。

于 2011-03-23T09:54:14.370 に答える
10

この投稿はそれをすべて非常にうまくまとめています:

http://novuscraft.com/blog/ravendb-and-the-repository-pattern

于 2012-02-23T23:06:26.830 に答える
8

親IDが1に等しいすべてのアイテムをフェッチする必要があるとしましょう。

まず、この方法でデータアクセスのニーズについて考えるのをやめます。

「親IDが1に等しいすべてのアイテムをフェッチする」必要はありませ。このようなデータ指向の方法で考えるのをやめようとするのに役立ちます。

必要なのは、特定の親を持つすべてのアイテムをフェッチすることです。これは、問題空間(アプリケーションのドメイン)に存在する概念です。

これをデータベースで外部キーとparentidという名前のフィールドを使用してモデル化するという事実は、実装の詳細です。これをカプセル化し、アプリケーション全体にリークしないでください。

1つの方法は、IQueryable List()を使用してすべてのドキュメントを取得し、where句を追加して、parentidが1に等しいアイテムを選択することです。RavenDBではインデックス機能を使用できないため、これは悪い考えのようです。したがって、もう1つのアプローチは、リポジトリにIEnumerable Find(string index、Func predicate)のようなものを含めることですが、これも悪い考えのようです。

これらは両方とも悪い考えです。あなたが提案しているのは、リポジトリまたはクエリを呼び出すコードがスキーマの知識を持っていることを要求することです。

リポジトリの利用者が親のフィールドがあることを気にかけたり、知ったりする必要があるのはなぜですか?これが変更された場合、問題空間の特定の概念の定義が変更された場合、コード内の何箇所を変更する必要がありますか?

特定の親を持つアイテムをフェッチするすべての場所。

これは悪いことです、それはカプセル化のアンチテーゼです。

私の意見では、クエリを明示的な概念としてモデル化する必要があります。ラムダや文字列が渡されて使用されるのではありません。

仕様パターン、リポジトリ上の名前付きクエリメソッド、クエリオブジェクトパターンなどを使用して、クエリを明示的にモデル化できます。

これは十分に一般的ではなく、RavenDBから一般的なSQLサーバーに変更する場合に備えてこのメソッドを実装する必要があります。

まあ、それFuncあまりにも一般的です。繰り返しになりますが、このようなクエリ方法を使用するために、消費するコードが何を知る必要があるかを考えてください。これを行うことで、コードの上位層をDBスキーマに直接結び付けることになります。

また、あるストレージエンジンから別のストレージエンジンに変更する場合、パフォーマンスがストレージエンジン固有の支援(たとえば、Ravenのインデックス)を使用するのに十分な要素であるクエリの再実装を回避することはできません。

于 2011-03-23T01:08:45.003 に答える
5

私は実際にあなたがリポジトリパターンを使用することを思いとどまらせます。ほとんどの場合、それは過剰に設計されており、実際にはコードをより複雑にします。

Ayendeは最近、その目的のために多くの投稿を行いました。

RavenのネイティブAPIに対して作成することをお勧めします。

私の回答が一般的すぎると感じた場合は、別の抽象化レイヤーを使用することで得たいと思う利点をいくつか挙げてください。議論を続けることができます。

于 2011-03-23T00:45:31.757 に答える