生成LinqToEntities Where语句取决于用户选择

时间:2012-02-08 08:39:37

标签: c# entity-framework optimization

我有用户界面,用户可以为该列选择网格列(如年龄)和运算符(小于,等于或大于)。

然后根据选择过滤网格数据。

我有以下类,这些类是从来自客户端的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语句。现在我只需要比较不同的解决方案。

5 个答案:

答案 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.
        }