NHibernate 3+ と Entity Framework 4.1 をテストするプロジェクトを作成し、リポジトリにラップして、インターフェイスなどを使用して非常にテストしやすくしました。
どちらの ORM もリポジトリの外部に公開したくありません (IQueryables も公開しません)。すべてはそのレイヤーで処理する必要があり、フェッチを抽象的な方法で処理しようとするまでは、すべてがうまくいきました。
積極的な読み込みを追加する Microsoft の実装では、Include 関数でマジック ストリング (yuck) または Linq 式 (yay) を使用します。それらの構文は次のようになります。
IQueryableThing.Include(o => o.Person);
IQueryableThing.Include(o => o.Company.Contact);
IQueryableThing.Include(o => o.Orders.Select(p => p.LineItem.Cost);
1 つ目は、関連する人物をロードするだけです。(親) 2 番目は、関連する会社と各会社の連絡先を読み込みます。(親と祖父母)。3 つ目は、関連するすべての注文、項目、および各注文の費用を読み込みます。
これはかなり洗練された実装です。
Hibernate は少し異なるアプローチを使用します。彼らはまだLinq式を使用していますが、拡張メソッドをより頻繁に使用しています(流暢なアプローチ)。
IQueryableThing.Fetch(o => o.Person);
IQueryableThing.Fetch(o => o.Company).ThenFetch(o => o.Contact);
IQueryableThing.FetchMany(o => o.Orders).ThenFetch(p => p.LineItem).ThenFetch(q => q.Cost);
(3 行目の構文が正しいかどうかはわかりません)
式のリストを別のクラスにカプセル化し、それらの式をそのクラス内の IQueryable に適用できます。したがって、Microsoft 式の構文を標準化し、式ツリーをたどって各式を再構築することで、それを NHibernate の構文に変換する必要があります。
これは本当にトリッキーな部分です。IQueryable の正しい関数を呼び出すために、特定の操作順序を維持する必要があります (Fetch または FetchMany のいずれかで開始し、その後はそれぞれ「ThenFetch」または「ThenFetchMany」にする必要があります)。 ExpressionVisitor クラスで。
編集:最終的に、プロパティ、コレクション、およびコレクションの選択の任意のレベルのネストを取り、式の配列を生成する式パーサーを作成しました。残念ながら、組み込みの Fetch 拡張メソッドは LambdaExpression をパラメーターとして取りません。
私が現在立ち往生している部分は、nHibernate からの組み込みの Fetch 定義を使用できないことです。Remotion ライブラリの関数を直接叩くか、パーサーを満たす独自の拡張メソッドを登録する必要があるようです。
ファンキー。