locked
How to use "Or" in PredicateBuilder? RRS feed

  • Question

  • User-1651604128 posted

    In my mvc web app, I built a search function using PredicateBuilder,

    here is the codes:

     public static class PredicateBuilder
        {
            public static Expression<Func<T, bool>> True<T>() { return f => true; }
            public static Expression<Func<T, bool>> False<T>() { return f => false; }
    
            public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
                                                                Expression<Func<T, bool>> expr2)
            {
                var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
                return Expression.Lambda<Func<T, bool>>
                      (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
            }
    
            public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
                                                                 Expression<Func<T, bool>> expr2)
            {
                var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
                return Expression.Lambda<Func<T, bool>>
                      (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
            }
        }

    You can see that I defined "Or" method in it, now I need to know how to use it in my C# codes.

    ....
    if (!string.IsNullOrEmpty(ContactName))
                    {
                        predicate = predicate.And(t => t.CONTACT_NAME.ToString().Contains(ContactName));
                    }
                   
                    if (!string.IsNullOrEmpty(ClientName))
                    {
                       //predicate = predicate.Or(t => t.Name1.ToString().Contains(ClientName)), (t => t.Name2.ToString().Contains(ClientName))) ;
    // Here I need to check if Name1 == ClientName or Name2 = ClientName
    //and this or logic will be combined with the "and" before this line of code and after it.
                    }
                   if (!string.IsNullOrEmpty(Status))
                    {
                        predicate = predicate.And(t => t.STATUSCode.ToString().Contains(Status));
                    }
    

    Thursday, December 6, 2018 6:11 PM

All replies

  • User475983607 posted

    You can see that I defined "Or" method in it, now I need to know how to use it in my C# codes.

    It's an extension method.  So only one parameter is as "this" is the other parameter.   See the C# Programming guide.

    predicate = predicate.Or(t => t.Name1.ToString().Contains(ClientName));
    predicate = predicate.Or(t => t.Name2.ToString().Contains(ClientName));

    It looks like the source code was copied from the following book excerpt which also explains how to use the Or; http://www.albahari.com/nutshell/predicatebuilder.aspx

    Thursday, December 6, 2018 6:37 PM
  • User-1651604128 posted

    mgebhard

    Peter Cong

    You can see that I defined "Or" method in it, now I need to know how to use it in my C# codes.

    It's an extension method.  So only one parameter is as "this" is the other parameter.   See the C# Programming guide.

    predicate = predicate.Or(t => t.Name1.ToString().Contains(ClientName));
    predicate = predicate.Or(t => t.Name2.ToString().Contains(ClientName));

    It looks like the source code was copied from the following book excerpt which also explains how to use the Or; http://www.albahari.com/nutshell/predicatebuilder.aspx

    Hi mgebhard,

    I have tried your codes, there is no compile error or run time error, but when I test the real data to filter the data, it seems it is not right.

    The data I tried in these 2 Name1, Name2 fields are not returned, instead, it ignores the Name1 or Name2 fields,

    From what I can see that, since the statement of before the this "or" or after the "or" are all using "And", so it always returns the previous predicate results, not the result of after "or"

    I also tried this, but I got recursive run time error,

    predicate = predicate.And(predicate.Or(t => t.Name1.ToString().Contains(ClientName)));
    predicate = predicate.And(predicate.Or(t => t.Name2.ToString().Contains(ClientName)));

    or the second option is that if I can find the current record to check if the Name1 field has data, if its Name1 field contains data, then I still use 'And' to filter the current Name1 field, and do the same thing for Name 2 field, in this way, I will not use 'or' logic, so all use 'And' with other fields.

    But the thing is I can not find a way to find the current return record data of Name1.

    The third option is to use 2 fields (Name1 and Name2 ) in the filter form, so I can use 'And' to filter the two fields, but the requirement only asks one Name filter field.

    Friday, December 7, 2018 1:13 PM
  • User475983607 posted

    If I understand correctly, your question has nothing to do with understanding the code copied from Internet in your original post.  The actual problem is fulfilling a business requirement and you want to craft the logic in a single method.

    I would create several distinctive methods rather than trying to crafting a generic predicate with mixed logical "AND" and "OR".  The reasoning is "AND and "OR" are generally grouped to control the order of operations.  In other words, if you want to search for contract name then build a method to search by contact name.  Follow the SOLID principles and "Single Responsibility".

    Friday, December 7, 2018 2:14 PM