2016-07-05 7 views
5

背景

特定の日付以前に作成されたレコードに結果をフィルタリングする.Includeを構築する必要があります。元のLINQステートメントのオブジェクトの種類はわかりませんが、私はそれらを見つけることになります(たくさんのフープで動作していますが)。元LINQを書くときつまり、開発者はこれらの関係を入力していません(動的にビルドする場所にフィルタを含める

  A -> Ac 
     /\ 
    Bc <- B \ 
    / \ 
Cc <- C  D -> Dc 

オブジェクトAcBcCc、およびDcはすべて動的に発見された:

私はこのようなオブジェクトのグラフを持っていますステートメント)。これらは、IQueryable式に追加する必要があり、特定のDateTimeまでの値のみを返す必要があります。

コードこれまで

私は、ラムダを構築し、日付を比較する機能を構築しようとしました。これまでのところ、元のクエリがA.Include(x => x.B).Include(x => x.B.Select(y => y.C)であれば、文字列"A.B.Bc"を作成できます。したがって、A、B、およびBcの型とその関係を知ることができます。

private static IQueryable<T> FilterChangeTrackerToDate<T>(this IQueryable<T> query, string includeString, DateTime targetDateTime) 
{ 
    var param = Expression.Parameter(typeof(T), "x"); 

    var prop = Expression.Property(param, includeString + ".CreatedUtc"); 

    var dateConst = Expression.Constant(targetDateTime); 

    var compare = Expression.LessThanOrEqual(prop, dateConst); 

    var lambda = Expression.Lambda<Func<T, bool>>(compare, param); 

    return query.Where(lambda); 
} 

問題は"A.B.Bc.CreatedUtc"は、日付プロパティをロードするための正しい方法ではありませんので、上記のコードがクラッシュするということである - 私は.Select文を介してこれを横断する必要があります。

問題

負荷レコードとフィルタそれら両方のために、私は動的に(ありがたいことに、継承に静的基づいて、)私は必要な値を引き出すために.Selectを構築する必要がありますそれらの値を匿名型に入れて、.Where()でフィルタリングすることができます。検証するコンパイル時の型がなく、リフレクションを乱用して動作させる必要があるため、最小限のジェネリックスでこれを行う必要があります。

基本的に、私はこれを作成する必要があります。

.Select(x => new 
{ 
    Bc = x.B.Select(z => z.Bc.Select(y => y.CreatedUtc).Where(q => q > DateTime.UtcNow)), 
    A= x 
}) 

を動的に、ネストの任意のレベルのために、文字列「A.B.Bc」を使用します。

リソース

私はメソッドが含まEFをフィルタリングする方法を説明しましたところです: LINQ To Entities Include + Where Method

動的選択を作成し、それが唯一のトップレベルの値を選択していると思われない程度この投稿会談をそれは私の問題のために必要な部品の残りの部分を構築することができますように:System.Linqのを使用してHow to create LINQ Expression Tree to select an anonymous type

ダイナミックLINQの

query = (IQueryable<T>) query.Select(includeString + ".CreatedUtc"); 

includeString = "B.Bc"が、これは私の例外与える::動的ライブラリは、I紀元前のオフCreatedUtc値にアクセスしようとした私はSystem.Linq.Dynamicは何が必要であると考えてい

Exception thrown: 'System.Linq.Dynamic.ParseException' in System.Linq.Dynamic.dll 

Additional information: No property or field 'Bc' exists in type 'List`1' 

答えて

2

を。もともとは、マイクロソフトからScottGuによって書かれたライブラリだし、それはあなたがそのような文字列からLINQクエリを構築することができます:

IQueryable nestedQuery = query.Select("B.Bc.CreatedUtc"); 

クエリがIQueryable<A>です。

このライブラリにはいくつかのフォークがあります。 hereから始めることができます。クエリ言語に関するドキュメントはhereです。またhereいくつかの追加機能を持つバージョンがあり、hereはdotnet.coreバージョンです。

UPD1: ThisライブラリはSelectMany拡張メソッドを欠いているがthis一つは持っています。

query.SelectMany("B").SelectMany("Bc").Select("CreatedUtc"); 
+0

私は、文字列 '「B.Bc.CreatedUtcを」'含まれている場合、私はこのエラーを取得:: '追加情報を:いいえプロパティまたはフィールド「Bcが」型では存在しないので、後者のライブラリで次の操作を行うことができます'List'1''。ネストされたグラフを正しく探索しているようには見えませんか? – Max

+0

ここにコードをもっと表示できますか? –

+0

メインポストを更新しました。 – Max

関連する問題