剣道グリッドを使用するMVCサイトがあり、動的フィルタを実装しようとしています。私が表示しているデータには、1対多のテーブルがいくつか含まれています。たとえば、私は人の行を持っている、各人が0以上の項目を割り当てられていることができます。私は、グリッド内の平坦化されたリストを表示しています:LINQ to Entities文字列ベースの動的場所
Bob | Item 1, Item 2
Jane | Item 3
を私はアイテム欄にハードコードするフィルタであれば、それは次のようになります。
people.Where(p=> p.Items.Any(i=>i.name.contains("Item 1"))).ToList()
私が思い付くしたいです式ツリーを構築するための一般的な方法です。異なる1対多のフィールドをフィルタリングしたり、異なる比較(例:contains、startswith、equalsなど)を実行することもできます。理想的には私は次の構文で拡張メソッドを持っているでしょう:
public static IQueryable<TEntity> Where(this IQueryable<TEntity> source, string tableName, string fieldName, string comparisonOperator, string searchVal) where TEntity : class
その後、私は複数の1対多のテーブルにクエリを実行できます。
if(searchOnItems)
persons = persons.Where("Items", "name", "Contains", "item 1);
if(searchOnOtherTableName)
persons = persons.Where("OtherTableName", "name", "Equals", "otherSearchValue);
persons.ToList();
私は出発点としてLINQ to Entities string based dynamic OrderByを使用しようとしています概念は似ているので、私はGenerateSelectorメソッドを変更する方法を理解できません。どんなアイデアでも大歓迎です。
編集 - 私のコードは閉鎖されたネットワーク上にあるので、私が努力しているものを複製するのに最善を尽くします。ここで私が修正しようとしているコードです。コメントブロックは私が立ち往生した場所です。上記の "Where"拡張メソッドを呼び出す例は、依然として有効です。
public static IQueryable<TEntity> Where<TEntity>(this IQueryable<TEntity> source, string tableName, string fieldName, string comparisonOperator, string searchVal) where TEntity : class
{
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, "Where", tableName, fieldName, comparisonOperator, searchVal);
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
}
private static MethodCallExpression GenerateMethodCall<TEntity>(IQueryable<TEntity> source, string methodName, string tableName, String fieldName, string comparisonOperator, string searchVal) where TEntity : class
{
Type type = typeof(TEntity);
Type selectorResultType;
LambdaExpression selector = GenerateSelector<TEntity>(tableName, fieldName, comparisonOperator, searchVal, out selectorResultType);
MethodCallExpression resultExp = Expression.Call(typeof(Queryable), methodName,
new Type[] { type, selectorResultType },
source.Expression, Expression.Quote(selector));
return resultExp;
}
private static LambdaExpression GenerateSelector<TEntity>(string tableName, String fieldName, string comparisonOperator, string searchVal, out Type resultType) where TEntity : class
{
// Create a parameter to pass into the Lambda expression (Entity => Entity.OrderByField).
var parameter = Expression.Parameter(typeof(TEntity), "Entity");
PropertyInfo property = typeof(TEntity).GetProperty(tableName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);;
Expression propertyAccess = Expression.MakeMemberAccess(parameter, property);;
/************************************************/
//property is now "TEntity.tableName"
//how do I go another step further so it becomes "TEntity.tableName.comparisonOperator(searchVal)"
/************************************************/
resultType = property.PropertyType;
// Create the order by expression.
return Expression.Lambda(propertyAccess, parameter);
}
[ダイナミックLINQライブラリ](http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library)の使用についてはどうですか?あなたが提供する機能をチェックアウトする必要があります。おそらくそれはあなたを助けるでしょう。 DynamicQueryライブラリは、LINQデータプロバイダ(LINQ to SQL、LINQ to XML、LINQ to XML、LINQ to Entities、LINQ to SharePoint、LINQ to TerraServerなど)に対して使用できます。 – Legends
問題はGenerateSelectorメソッドを動作させることに問題があると言いますが、問題が発生しているコードは表示されません。コードに問題がある場合は、コードを表示する必要があります。 – Hogan