LINQ lambda expression append OR statement

后端 未结 5 1441
攒了一身酷
攒了一身酷 2020-12-21 03:39

If I want to append a AND statement to my query, I can do:

query = query.Where(obj=>obj.Id == id);

if(name.HasValue)
  query = query.Where(obj=>obj.Na         


        
相关标签:
5条回答
  • 2020-12-21 04:27

    Simply this if I'm not missing something:

    query.Where(obj=>obj.Id == id || (obj.Name == name && name.HasValue))
    

    You might want to read this question (my question...) and answer for more complicated scenarios:
    How to filter IEnumerable based on an entity input parameter

    0 讨论(0)
  • 2020-12-21 04:28

    Part of the problem is that you over write your original query. Your OR operation would be equivalent to:

    subquery1 = query.Where(obj=>obj.Id == id);
    subquery2 = query.Where(obj=>obj.Name == name);
    query = subquery1.Concat(subquery2).Distinct();
    

    As you can see, that becomes pretty unwieldy as well, however if You are going to do this form, then you must maintain the original sequence so that you can get both the right and left sides of the equation processed then you need to be sure duplicates get removed.

    Instead of all that, I would try to figure a way to build up that conditional statement dynamically using lambdas e.g.

    I haven't actually run this, but something like this should work.

    var cond = obj=>obj.Id == id;
    
    ...
    
    // need an or
    cond = obj=>cond(obj) || obj.Name == name;
    
    query = query.Where(obj=>cond(obj));
    

    Hope this gives you an idea.

    0 讨论(0)
  • 2020-12-21 04:29

    You can't do it natively. However, you can use PredicateBuilder to compose the query before you run it, and it supports ORs.

    var predicate = PredicateBuilder.False<Product>();
    predicate = predicate.Or (obj=>obj.Id == id);
    if(name.HasValue)  predicate = predicate.Or (obj=>obj.Name == name);
    
    return query.Where(predicate);
    
    0 讨论(0)
  • 2020-12-21 04:29

    I would use gdoron's solution, but if it seems unpractical for larger sets of queries, a slightly more complicated solution containing set operations might help you:

    var queryById = query.Where(obj => obj.Id == id);
    var queryByName = query.Where(obj => obj.Name == name);
    query = queryById.Union(queryByName);
    

    It gets much more difficult if your original query contains duplicate items.

    Another way may be using Expression to formulate your queries. You can modify the expression tree before executing it, so you can add more conditions to the Where sub-tree. That is a whole lot of work and it's an overkill on 99.9% (rough estimate :) ) of cases.

    0 讨论(0)
  • 2020-12-21 04:43

    I would just build this into a single condition:

    if (name.HasValue)
        query = query.Where(obj=>obj.Id == id && obj.Name == name);
    else
        query = query.Where(obj=>obj.Id == id);
    
    0 讨论(0)
提交回复
热议问题