Generating LinqToEntities Where statement depending on the user selection

吃可爱长大的小学妹 提交于 2020-01-02 20:14:32

问题


I have user-interface where user can select grid column (like age) and operator (lesser than, equals or greater than) for that column.

Grid data is then filtered according to the selection.

I have a following classes that are deserialized from the JSON that is coming from the client.

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

Due to the nature dynamically adding new columns for filtering I would like to create generic solution for accessing the data.

I would like avoid having huge amount if/switch statements like

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

Any ideas how to create more generic solution for the problem?

Update It seems that there many ways to accomplish cleaner solution than one billion if statements. Now I just need to compare different solutions.


回答1:


You could use Dynamic LINQ to create the query dynamically

Edit:

An example for Dynamic LINQ query would look like this, assuming that the column names in the grid are the same as the field names in the entity:

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:


You can use the PredicateBuilder to dynamically build up linq queries based on whatever youi want. That will help you build up a linq expression easily. As for the ugly switch that would grow and grow over time, I would suggest perhaps if "name" always related to a property in your linq expression (e.g. "age" --> .Age), then you should be able to get that with some reflection code - so you check if "name" does relate to a property of the same name, and if so build a filter for it..

HTH




回答3:


You can pass to the Where method a System.Linq.Expressions.Expression object that you compose from your input. Here is an example of how to compose predicate expressions for use with EF or Linq2Sql: Dynamically Composing Expression Predicates




回答4:


You can use ESQL instead of just LINQ:

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

you can easily generate string representation for your criteria based on the filter you have.

Here is the full reference to ESQL should you need it.




回答5:


You can use reflection code such as :

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


来源:https://stackoverflow.com/questions/9189986/generating-linqtoentities-where-statement-depending-on-the-user-selection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!