私は動的にlinqのクエリを作成する方法の研究を行っています。私はWebアプリケーションのUIを作成しています。UIを使用して、DBからプロパティを選択し、where句を設定してレポートを動的に作成できます。スタックまたは他のサイトで私が見たすべての質問は、動的なLinqとLinqKitを使用して問題を解決するために参照しています。 ここに例があります。しかし、構文を表現するための解決策が見つかりません。
// This attempts to grab out a title whose from the Database whose
// Copyright Date equals 2006
propName = "CopyrightDate";
Model.Titles.Where(t => t.GetType().GetProperty(propName).GetValue(t, null) == "2006");
このようなことをしたいのですが、Linq to Entitiesで行います。 Linq to entityはそのようなリフレクションをサポートしていません。すべてのデータを引き出してLinq to Objectを実行したくないのですが、DBが大きすぎます。これをDynamic Linqで記述する方法に関する提案。タイプをプロパティタイプにキャストして、標準の演算子(==、>、<など)で再評価できる場合のボーナスポイント。
Dynamic Linqを使用してクエリを書き換える方法は次のとおりです。
var propName = "CopyrightDate";
var propValue = "2006";
Model.Titles.Where(string.Format("{0}=@0", propName), propValue);
string.Format("{0}=@0", propName)
は、 Where
句のクエリ文字列を生成します。この場合、 "CopyrightDate=@0"
になります。 @0
は、 propValue
になるクエリのパラメーターを指定します。
何LINQツーエンティティ拡張メソッドの欲求は、あるWhere
Expression<Func<T, bool>>
。次のような式を作成できます。
// Create lambda expression: t => t.CopyrightDate == "2006"
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
var lambda = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(parameter, "CopyrightDate"),
Expression.Constant("2006")
),
parameter
);
T
は、 CopyrightDate
プロパティを含むクラスのタイプです。
var result = context.Titles
.Where(lambda)
.ToList();
もう少し一般的な解決策は次のとおりです。
Expression<Func<T, bool>> Comparison<T>(ExpressionType comparisonType,
string propertyName, object compareTo)
{
ParameterExpression parameter = Expression.Parameter(typeof(T), "t");
MemberExpression property = Expression.Property(parameter, propertyName);
ConstantExpression constant = Expression.Constant(compareTo);
Expression body = Expression.MakeBinary(comparisonType, property, constant);
return Expression.Lambda<Func<T, bool>>(body, parameter);
}