5

Let's say we are using EF6, and db is the EF DbContext. Let's say the user could enter five possible queries:

  1. Get cars where age EQUALS 10.
  2. Get cars where age IS LESS THAN 10.
  3. Get cars where age IS MORE THAN 10.
  4. Get cars where age is NOT EQUAL to 10.
  5. Get carss where age is ANY.
    enum Operator
    {
        EQUAL,
        NOT_EQUAL,    
        LESS_THAN, 
        MORE_THAN,
        ANY
    };

    var operator = //some user selected operator, out of the ones available in the enum above
    var carAge = //int selected by user to specify desired age
    List cars; 

    switch(operator)
    {
        case Operator.EQUAL 
        {
            cars = db.Cars.Where(c=> c.Age == carAge).ToList(); 
        }
        case Operator.NOT_EQUAL 
        {
            cars = db.Cars.Where(c=> c.Age != carAge).ToList(); 
        }
        case Operator.LESS_THAN 
        {
            cars = db.Cars.Where(c=> c.Age  c.Age > carAge).ToList(); 
        }
        case Operator.ANY 
        {
            cars = db.Cars.ToList(); 
        }
    }

How do I do this more efficiently? The switch operator seems silly. It looks like this article is answering the question, but I don't fully understand.

We do have an answer on dynamically building multiple queries, but that's a different part of what I want (would apply if question was "User can search for both car age and mileage, or neither).

Edit: To clarify in response to a comment, my "goal" is any standard search, using the car example, a user would have a number of fields where they can select operators. They can use any, all, or no fields, e.g.

Mileage: Operator, Value
Year: Operator, Value
Brand: (is/is not, for example), Car brands

Community
  • 1
  • 1
VSO
  • 11,546
  • 25
  • 99
  • 187
  • What are you trying to do first off. If you need alot of dynamic queries, you have a few options, 1. OData, 2. Dynamic Linq, 3. Build your own expression trees. Chances are you should just use dynamic linq, or write your own expression tree, but learning that might be complicated and if you have a time limit your should use dynamic linq – johnny 5 May 23 '16 at 01:49
  • This is actually just a personal curiosity into "how is this properly done". This is trivial with MongoDb C# driver, and it seems weird that it's so convoluted with what is pretty much THE big business language/framework. I will update q. Also, I will check out dynamic linq, not even sure what it is. OData isn't really what I want. We use it for pagination and such on SQL queries, but I have found that it can't do a lot of basic things. – VSO May 23 '16 at 01:55

1 Answers1

7
    Expression<Func<T, bool>> Build<T, TProperty>(Expression<Func<T, TProperty>> property, Operator op, TProperty value)
    {
        if (op == Operator.ANY)
        {
            return e => true;
        }

        var left = property.Body;   //you need to check if it's a valid property visit
        var right = Expression.Constant(value);
        BinaryExpression body;

        switch (op)
        {
            case Operator.EQUAL:
                body = Expression.Equal(left, right);
                break;
            case Operator.NOT_EQUAL:
                body = Expression.NotEqual(left, right);
                break;
            case Operator.LESS_THAN:
                //you'd better check if < operator is available for the type
                body = Expression.LessThan(left, right);
                break;
            case Operator.MORE_THAN:
                body = Expression.GreaterThan(left, right);
                break;
            default: throw new NotSupportedException();
        }

        return Expression.Lambda<Func<T, bool>>(body, property.Parameters[0]);
    }

Usage var bmw = Build<Car, string>(c => c.Brand, Operator.EQUAL, "BMW");

Cheng Chen
  • 42,509
  • 16
  • 113
  • 174
  • Could you please explain this answer a bit - as I am working on a similar solution - or point us to some sort of article/documentation – Dawood Awan Nov 10 '18 at 20:53
  • @DawoodAwan It's a long story, try to start with [Expression Trees](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/) – Cheng Chen Nov 12 '18 at 10:02