我有用户界面,用户可以为该列选择网格列(如年龄)和运算符(小于,等于或大于)。
然后根据选择过滤网格数据。
我有以下类,这些类是从来自客户端的JSON反序列化的。
/// <summary>
/// Filter for reducing grid results
/// </summary>
public class Filter
{
/// <summary>
/// Name of the column
/// </summary>
public string name;
public string value;
public int @operator { private get; set; }
public Operator Operator()
{
return (Operator) @operator;
}
}
public enum Operator
{
None = -1,
LesserThan = 0,
Equals = 1,
GreaterThan = 2
}
由于性质动态添加新列进行过滤,我想创建用于访问数据的通用解决方案。
我想避免使用大量if / switch语句,如
switch(columnName)
{
case "age":
{
if(operator == Operator.LesserThan)
{
query = entities.Where(o => o.Age < age);
}
else if (operator == Operator.GreaterThan)
{
query = entities.Where(o => o.Age > age);
}
etc.
break;
}
etc.
}
如何为这个问题创建更通用的解决方案?
更新 似乎有很多方法可以实现更清洁的解决方案而不是10亿if语句。现在我只需要比较不同的解决方案。
答案 0 :(得分:1)
您可以使用PredicateBuilder根据您的需要动态构建linq查询。这将有助于您轻松构建linq表达式。至于随着时间的推移会增长和增长的难看的开关,我建议如果“name”总是与你的linq表达式中的属性相关(例如“age” - > .Age),那么你应该能得到使用一些反射代码 - 所以你检查“name”是否与同名的属性有关,如果有,为它构建一个过滤器..
HTH
答案 1 :(得分:1)
您可以使用Dynamic LINQ动态创建查询
编辑:
动态LINQ查询的示例如下所示,假设网格中的列名与实体中的字段名相同:
string queryString;
queryString = columnName;
if(operator == Operator.LesserThan)
{
queryString += " < ";
}
else if (operator == Operator.GreaterThan)
{
queryString += " > ";
}
etc.
queryString += age.ToString(); // Or use bind variables, haven't tried that myself in dynamic LINQ
query = entites.Where(queryString);
答案 2 :(得分:1)
您可以将您从输入中组成的System.Linq.Expressions.Expression对象传递给Where方法。以下是如何组合用于EF或Linq2Sql的谓词表达式的示例: Dynamically Composing Expression Predicates
答案 3 :(得分:1)
您可以使用ESQL而不仅仅使用LINQ:
Context.Entities
.Where("it.Age > @Age", new[] { new ObjectParameter("Age", age } );
您可以根据自己的过滤器轻松生成条件的字符串表示。
如果您需要,请full reference to ESQL。
答案 4 :(得分:1)
您可以使用反射代码,例如:
String columName; //your dynamic columnName
if(operator == Operator.LesserThan)
{
query = entities.Where(o => o.GetType().GetProperty(columName).GetValue(o, null) <columName);
}
else if (operator == Operator.GreaterThan)
{
etc.
}