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是的,你是对的。这是一个正确的观点。未看到第一条注释。不完全确定,但您是否缺少一个表达式。是否转换常量值的?我想我不久前必须使用它,否则它会抛出异常。