代码之家  ›  专栏  ›  技术社区  ›  Scott Lance

使用动态字段名查询具有LINQ的实体

  •  2
  • Scott Lance  · 技术社区  · 14 年前

    现在,我希望在查询数据库时能够使用该字段名并将其应用于我的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表达式树,但失败了,在使用动态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>();
    }
    

    更新

    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、 “名字”,但我不能让它在一个地方工作。有什么建议吗?我的代码如下:

    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);
    
    3 回复  |  直到 7 年前
        1
  •  8
  •   Community Egal    7 年前

    经过反复尝试和搜索,我意外地发现了另一篇涉及同一问题的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);
    

    有一些希望相当容易的修改,我应该能够让这与任何类型的工作。

    再次感谢您的回答;演包文

        2
  •  5
  •   John Bowen    14 年前

    entities.People.Where(p => (p.GetType().GetProperty(key).GetValue(p, null) as string) == fieldValueDictionary[key])
    
        3
  •  1
  •   Ani    14 年前
      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; ;
            }