【问题标题】:Generating LinqToEntities Where statement depending on the user selection根据用户选择生成 LinqToEntities Where 语句
【发布时间】:2012-02-29 16:35:36
【问题描述】:

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

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

我有一个从来自客户端的 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.
}

任何想法如何为该问题创建更通用的解决方案?

更新 似乎有很多方法可以完成比十亿个 if 语句更清洁的解决方案。现在我只需要比较不同的解决方案。

【问题讨论】:

    标签: c# entity-framework optimization


    【解决方案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);
    

    【讨论】:

    • 您能否分享一个适用于 OP 用例的示例,以使您的答案更具描述性和完整性?
    【解决方案2】:

    您可以使用PredicateBuilder 根据您想要的任何内容动态构建 linq 查询。这将帮助您轻松构建 linq 表达式。至于会随着时间的推移不断增长的丑陋开关,我建议如果“名称”总是与您的 linq 表达式中的属性相关(例如“年龄”-> .Age),那么您应该能够得到它使用一些反射代码 - 因此您检查“名称”是否与同名的属性相关,如果是,则为它构建一个过滤器..

    HTH

    【讨论】:

    • 非常好!我认为这正是我所需要的。现在我只需要检查有关 Dynamic LINQ 的另一个答案并决定哪个更合适。然后我会选择获胜的答案。
    【解决方案3】:

    您可以将 System.Linq.Expressions.Expression 对象传递给 Where 方法,该对象由您的输入组成。下面是一个如何组合用于 EF 或 Linq2Sql 的谓词表达式的示例: Dynamically Composing Expression Predicates

    【讨论】:

      【解决方案4】:

      您可以使用 ESQL 而不仅仅是 LINQ:

      Context.Entities
          .Where("it.Age > @Age", new[] { new ObjectParameter("Age", age } );
      

      您可以根据您拥有的过滤器轻松地为您的条件生成字符串表示形式。

      如果您需要,这里是full reference to ESQL

      【讨论】:

        【解决方案5】:

        您可以使用反射代码,例如:

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

        【讨论】:

        • 我觉得很好很简单。
        猜你喜欢
        • 2017-09-12
        • 2015-05-17
        • 1970-01-01
        • 2019-07-09
        • 1970-01-01
        • 2012-12-02
        • 1970-01-01
        • 2015-12-06
        • 1970-01-01
        相关资源
        最近更新 更多