0

Linq式の変換について厄介な質問があります。よく調べてみましたが、この件をカバーしていると思われるものは見つかりませんでした。少なくともラムダの作成とメソッドへの受け渡しに関しては、Linqにかなり精通していますが、Expressionに関するものはやや弱いです。

まず、いくつかのコンテキスト:私は多くのDDD風のプロジェクトで使用されているNHibernateに基づく一般的な永続化ソリューションを持っています。アグリゲート内の特定の子のコレクションが本質的に無限である(つまり、実際には非常に大きい)可能性がある特殊なケースでは、コレクション全体をメモリにロードすることは決して受け入れられないため、セットまたはバッグを単純にマップすることはできません。このアーキテクチャでは、APIを使用するコードがリポジトリと直接通信してクエリを実行したり、その方法で結果を制限したりすることはできません。もちろん、APIにコレクションをまったく持たず、代わりに子オブジェクトの関連するサブセットを取得するメソッドを公開することはできません(これが機能しない場合は、これを実行します)が、少し異なることをしようとしています。そして、私はほとんどそれを機能させています...

これらのプロジェクトはFluent(自動マッピングではない)でマッピングされているため、フォームでベースマップクラスにメソッドを追加しました

HasManyQueryable<TCollection>(Expression<Func<T, IQueryable<TCollection>>> memberExpression, Expression<Func<T, TCollection, bool>> selector)

PropertyInfoこのメソッドは、最初のメソッドExpression(マップするメンバーを指定する)から関連性を導き出します。セレクターExpressionには、通常のNHibernateマッピングの代わりに、親オブジェクトと子オブジェクトの間の関係が含まれています。

Userしたがって、ドメインタイプ(T上記)のセレクターがマップにあるとします。

HasManyQueryable<Transaction>(x => x.Transactions, (u, t) => t.User == u);

これは、指定されたuTransactionsであるすべてのサブセットと、であるプロパティの間のマッピングを指定します。実際のオブジェクトを作成するとき、これを次のように変換する必要がありますTransaction.UserUser User.TransactionsIQueryable<Transaction>User

Expression<Func<Transaction, bool>> expression = (t => t.User == this)

構築されているオブジェクトthisはどこにありますか。つまり、にマップする方法を示す一般的なルールを使用して、これをにマップするためのルールに変換しUserたいと思います。次に、この式を使用して、Linqクエリを実行することにより、リポジトリからを生成できます。UsersTransactions UserTransactionsIQueryable<Transaction>

return Repository.For<Transaction>().Where(selector);

これは、セレクターがである場合にのみ機能しますFunc<Transaction, bool>。したがって、私の最終的な必要性は、元の式を変換することです。これにより、が生成さFunc<User, Transaction, bool>Func<Transaction, bool>ます。

これによりIQueryable、すべてのクエリ操作がLinqからNHibernateクエリとして実行されるコレクションが得られるため、コレクション全体がメモリに読み込まれることはありません(はい、実際にそれを実行するクエリをフレーム化できることはわかっていますが、コードレビュー時にそれらをキャッチできます)。

ふぅ。それが理にかなっていることを願っています。

私を正しい方向に向けることができるリートエクスプレッションの書き直しスキルを持っている人はいますか?

4

1 に答える 1

1

ドメインの観点からあなたがやろうとしていることについて、私は正直なところ少し迷っています。しかし、コードの観点からは、必要なのはカリー化された関数、つまりユーザーを取得してFuncを生成するメソッドだけのように思えます。同じことをインラインで行うこともできますが、メソッドの例はこれです。

Func<Transaction,bool> UserSpecificSelector(User user,
                                            Func<User,Transaction,bool> selector)
{
    return t => selector(user, t);
}

したがって、ユーザー固有のセレクターを取得するには、次のようにします...

Func<User, Transaction, bool> selector = // whatever;
User user = //whatever;
Repository.For<Transaction>().Where(t => selector(user, t));

独自のクエリプロバイダーを実装している場合を除いて、階層を直接操作する必要がExpressionあるとは思えません。この場合は実装していません。

于 2011-08-24T20:22:27.983 に答える