ASP.NET MVCで動的検索画面を作成しました。エンティティからのフィールド名をリフレクションで取得したので、ビュー内のすべてのフィールドを表示するのではなく、検索するフィールドをユーザーが選択できるようにしました。
検索結果がコントローラにポストバックされると、FieldNameとValueを含むFormCollectionが返されます。検索対象のフィールドの数がわからず、FormCollectionにはユーザーが選択したフィールドしか含まれていません。
私は今データベースをクエリするときに、そのフィールド名を取得してLINQステートメントに適用できるようにしたいと考えています。
public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary)
{
List<People> searchResults = new List<People>();
foreach (string key in fieldValueDictionary.Keys)
{
searchResults.Add(entities.People.Where(p => p.<use the key string as the fieldName> == fieldValueDictionary[key]));
}
return searchResults;
}
私が "keyNameをfieldNameとして使用する"のところでは、p => p.FirstName == fieldValueDictionary [key] key = "FirstName"のようになります。私は試してラムダ式ツリーを使用することに失敗し、Dynamic LINQで少し成功しました。唯一の他の選択肢は、次のようなことです。
public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary)
{
IQueryable<People> results = entities.People;
foreach (string key in fieldValueDictionary.Keys)
{
switch (k)
{
case "FirstName": results = results.Where(entities.People.Where(p => p.FirstName == k);
case "LastName": results = results.Where(entities.People.Where(p => p.LastName == k);
// Repeat for all 26 fields in table
}
}
return results.ToList<People>();
}
更新 :私はラムダ式木の研究を次の記事を通じて行ってきました:
ラムダ式+ linq + OrderByDescendingを動的に作成する
LINQ:ラムダ式を実行するパラメータとして渡し、メソッドによって返す
私はlambdaを次のように出力するまでは得ました: "p => p.FirstName"、しかし私はこれをどこで動作させることはできません。助言がありますか?私のコードは以下の通りです:
MemberInfo member = typeof(People).GetProperty("FirstName");
ParameterExpression cParam = Expression.Parameter(typeof(People), "p");
Expression body = Expression.MakeMemberAccess(cParam, member);
var lambda = Expression.Lambda(body, cParam);
もっと多くの試行錯誤や検索をした後、私は誤って同じ問題を扱う別のSO投稿を見つけました:
InvalidOperationException: 'System.Linq.Queryable'型の 'Where'メソッドは、指定された引数と互換性がありません
ここで動作する変更されたコードは次のとおりです。
IQueryable query = entities.People;
Type[] exprArgTypes = { query.ElementType };
string propToWhere = "FirstName";
ParameterExpression p = Expression.Parameter(typeof(People), "p");
MemberExpression member = Expression.PropertyOrField(p, propToWhere);
LambdaExpression lambda = Expression.Lambda<Func<People, bool>>(Expression.Equal(member, Expression.Constant("Scott")), p);
MethodCallExpression methodCall = Expression.Call(typeof(Queryable), "Where", exprArgTypes, query.Expression, lambda);
IQueryable q = query.Provider.CreateQuery(methodCall);
うまくいけば簡単に変更できるものがあれば、これをどんなタイプでも使えるはずです。
あなたの答えをもう一度おねがいします。Ani&John Bowen
PropertyInfoから値を取得しようとしましたか?
entities.People.Where(p => (p.GetType().GetProperty(key).GetValue(p, null) as string) == fieldValueDictionary[key])