Linq PredicateBuilder with conditional AND, OR and NOT filters.

Posted by richeym on Stack Overflow See other posts from Stack Overflow or by richeym
Published on 2010-06-15T09:33:06Z Indexed on 2010/06/17 16:23 UTC
Read the original article Hit count: 461

Filed under:
|
|
|

We have a project using LINQ to SQL, for which I need to rewrite a couple of search pages to allow the client to select whether they wish to perform an and or an or search.

I though about redoing the LINQ queries using PredicateBuilder and have got this working pretty well I think. I effectively have a class containing my predicates, e.g.:

internal static Expression<Func<Job, bool>> Description(string term)
{
    return p => p.Description.Contains(term);
}

To perform the search i'm doing this (some code omitted for brevity):

public Expression<Func<Job, bool>> ToLinqExpression()
{
    var predicates = new List<Expression<Func<Job, bool>>>();
    // build up predicates here

    if (SearchType == SearchType.And)
    {
        query = PredicateBuilder.True<Job>();
    }
    else
    {
        query = PredicateBuilder.False<Job>();
    }

    foreach (var predicate in predicates)
    {
        if (SearchType == SearchType.And)
        {
            query = query.And(predicate);
        }
        else
        {
            query = query.Or(predicate);
        }
    }
    return query;
}

While i'm reasonably happy with this, I have two concerns:

  1. The if/else blocks that evaluate a SearchType property feel like they could be a potential code smell.
  2. The client is now insisting on being able to perform 'and not' / 'or not' searches.

To address point 2, I think I could do this by simply rewriting my expressions, e.g.:

internal static Expression<Func<Job, bool>> Description(string term, bool invert)
{
    if (invert)
    {
        return p => !p.Description.Contains(term);
    }
    else
    {
        return p => p.Description.Contains(term);
    }
}

However this feels like a bit of a kludge, which usually means there's a better solution out there. Can anyone recommend how this could be improved? I'm aware of dynamic LINQ, but I don't really want to lose LINQ's strong typing.

© Stack Overflow or respective owner

Related posts about c#

Related posts about LINQ