我在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;
}
我有“使用密钥字符串作为fieldName”,它就像p =&gt; p.FirstName == fieldValueDictionary [key]其中key =“FirstName”。我尝试过并且未能使用Lambda Expression Trees,并且在动态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>();
}
更新:我通过以下帖子研究了Lambda Expression Trees:
dynamically create lambdas expressions + linq + OrderByDescending
Parameter problem with Expression.Lambda()
LINQ: Passing lambda expression as parameter to be executed and returned by method
我已经得到一个lambda来输出以下内容:“p =&gt; 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);
答案 0 :(得分:7)
经过更多的反复试验和搜索后,我偶然发现了另一篇涉及同一问题的SO帖子:
以下是我修改后的代码:
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&amp;约翰鲍文
答案 1 :(得分:5)
您是否尝试过从PropertyInfo获取值?
entities.People.Where(p => (p.GetType().GetProperty(key).GetValue(p, null) as string) == fieldValueDictionary[key])
答案 2 :(得分:1)
public List<People> SearchPeople(Dictionary<string, string> fieldValueDictionary)
{
return !fieldValueDictionary.Any()
? entities.People
: entities.People.Where(p => fieldValueDictionary.All(kvp => PropertyStringEquals(p, kvp.Key, kvp.Value)))
.ToList();
}
private bool PropertyStringEquals(object obj, string propertyName, string comparison)
{
var val = obj.GetType().GetProperty(propertyName).GetValue(obj, null);
return val == null ? comparison == null : val.ToString() == comparison; ;
}