C# 具有动态列的LINQ where条件

C# 具有动态列的LINQ where条件,c#,entity-framework,linq,dynamic,linq-to-sql,C#,Entity Framework,Linq,Dynamic,Linq To Sql,我有这个密码 // IQueryable<General> query if (columnName == "Column1") { query = query.Where(x => x.Column1 == searchValue); } else if (columnName == "Column2") { query = query.Where(x => x.Column2 == searchValue); } else if (columnName

我有这个密码

// IQueryable<General> query

if (columnName == "Column1") 
{
  query = query.Where(x => x.Column1 == searchValue);
}
else if (columnName == "Column2") 
{
  query = query.Where(x => x.Column2 == searchValue);
}
else if (columnName == "Column3") 
{
  query = query.Where(x => x.Column3 == searchValue);
}
else if (columnName == "Column4") 
{
  query = query.Where(x => x.Column4 == searchValue);
}
// next zilions columns to come
// ...
//IQueryable查询
如果(columnName==“Column1”)
{
query=query.Where(x=>x.Column1==searchValue);
}
else if(columnName==“Column2”)
{
query=query.Where(x=>x.Column2==searchValue);
}
else if(columnName==“Column3”)
{
query=query.Where(x=>x.Column3==searchValue);
}
else if(columnName==“Column4”)
{
query=query.Where(x=>x.Column4==searchValue);
}
//下一篇文章
// ...

我的问题是。如何在“.Where”条件中通过x.Column作为参数?

您可以使用反射通过名称检索属性

x.GetType().GetProperty(propertyName,BindingFlags).SetValue(x,value)
// propertyName = "Column1" for example
// BindingFlags are most likely Instance, Public and Property (IIRC)
或者将PropertyInfo作为参数直接传递到方法中。您的选择取决于您希望向方法的使用者公开的抽象级别。

您可以使用和扩展方法。作为一个粗略的例子:

public class Foo
{
  public int Column1 { get; set; }
  public int Column2 { get; set; }
  ...
}

public static class FooExtensions
{
  // I would use the actual type here instead of object if you know the type.
  public static object GetProperyValue(this Foo foo, string columnName)
  {
    var propertyInfo = foo.GetType().GetProperty(columnName);
    var value = propertyInfo.GetValue(foo);
    // as well as cast value to the type
    return value;
  }
}

...

query = query.Where(x => x.GetProperyValue(columnName) == searchValue);
...

作为旁注,这不是一个设计良好的查询,因为每次向模型中添加列时,都需要更新
if
-
else
。它违反了中的O。

您可以手动创建谓词。使用此方法:

public static Expression<Func<General, bool>> CreatePredicate(string columnName, object searchValue)
{
    var xType = typeof(General);
    var x = Expression.Parameter(xType, "x");
    var column = xType.GetProperties().FirstOrDefault(p => p.Name == columnName);

    var body = column == null
        ? (Expression) Expression.Constant(true)
        : Expression.Equal(
            Expression.PropertyOrField(x, columnName),
            Expression.Constant(searchValue));

    return Expression.Lambda<Func<General, bool>>(body, x);
}
公共静态表达式CreatePredicate(字符串列名、对象搜索值)
{
var xType=类型(一般);
var x=表达式参数(xType,“x”);
var column=xType.GetProperties().FirstOrDefault(p=>p.Name==columnName);
var body=column==null
?(表达式)表达式。常数(真)
:表达式。相等(
Expression.PropertyOrField(x,columnName),
常量(searchValue));
返回表达式.Lambda(body,x);
}
现在您可以应用谓词:

IQueryable<General> query = //
var predicate = CreatePredicate(columnName , searchValue);
query = query.Where(predicate);
IQueryable查询=//
var predicate=CreatePredicate(columnName,searchValue);
query=query.Where(谓词);

“下一篇文章”您应该重构数据模型。为什么有这么多类似的专栏?用另一张桌子代替。然后,您的查询也变得非常简单和高效。您不能..不是以任何简单的方式..但是您不能直接传递
表达式过滤器Expression而不是传递(searchValue,columnName)吗?用作
query.Where(filterExpression)
columnName、searchValue从何而来?为什么要在该文件中指定它们way@TimSchmelter它的报告表列。。每列包含完全不同的数据。这样做的目的是让用户单独筛选每一列。@bommelding实际上我的答案应该与Linq To Sql一起使用(因为我使用的是表达式)@AleksAndreev-布丁的证据就在吃的时候。。。它真的有效吗?例如,在LINQtoEntities(我认为我们可以假设使用最多的
IQueryProvider
)中,它无法将方法转换为有效的方法SQL@AlexanderDerck是的,你是对的。这是一个正确的观点。未看到第一条注释。不完全确定,但您是否缺少一个
表达式。是否转换常量值的
?我想我不久前必须使用它,否则它会抛出异常。