根据用户选择生成LinqToEntities Where语句

本文关键字:LinqToEntities Where 语句 用户 选择 | 更新日期: 2023-09-27 18:23:48

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

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

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

根据用户选择生成LinqToEntities Where语句

您可以使用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);

您可以使用PredicateBuilder根据需要动态构建linq查询。这将帮助您轻松构建linq表达式。至于会随着时间的推移而增长的丑陋切换,我建议,如果"name"总是与linq表达式中的一个属性相关(例如"age"-->.age),那么你应该能够通过一些反射代码来获得它,所以你要检查"name"是否与同名的属性相关,如果是,则为其构建一个过滤器。

HTH

您可以将根据输入组成的System.Linq.Expressions.Expression对象传递给Where方法。以下是如何组合谓词表达式以与EF或Linq2Sql一起使用的示例:动态合成表达式谓词

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

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

您可以很容易地根据您的过滤器为您的条件生成字符串表示。

如果您需要的话,下面是对ESQL的完整引用。

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

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