2010-08-11 75 views
2

我在ASP.NET MVC中创建了一个动态搜索屏幕。我通过反射从实体中检索字段名称,以便我可以允许用户选择要搜索的字段而不是显示视图中的所有字段。使用Dyanmic字段名称查询LINQ的实体

当搜索结果回发给控制器时,我收到一个包含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; 
} 

在那里我有“使用密钥字符串作为字段名”吧会像p => p.FirstName == fieldValueDictionary [key]其中key =“FirstName”。我尝试过并且未能使用Lambda Expression Trees,并且在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>(); 
} 

更新:我已经通过以下职位进行研究Lambda表达式树:

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 => 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); 
+1

如果你想这样的动态行为,我真的觉得你会需要去学习如何去爱表达式树。 – 2010-08-11 22:51:53

回答

6

更大量的试验和错误和搜索后,我无意中发现了另一个SO贴子,讨论同一个问题:

InvalidOperationException: No method 'Where' on type 'System.Linq.Queryable' is compatible with the supplied arguments

这是我的作品修改后的代码:

 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); 

随着一些希望非常容易的修改,我应该能够得到这个与任何类型的工作。

再次感谢您的回答阿尼&约翰·鲍文

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; ; 
     } 
+0

在这种情况下这个实体是什么? – duardbr 2016-03-29 18:05:14

5

您是否尝试过正从的PropertyInfo价值?

entities.People.Where(p => (p.GetType().GetProperty(key).GetValue(p, null) as string) == fieldValueDictionary[key]) 
+1

Linq to Entities不支持GetValue()调用。我可以让这个想法起作用,但它要求我从数据库中获得完整的人员列表,然后通过它们进行全面的清单,比我清洁,但仍然不是我想要的。 – 2010-08-12 12:53:56