0

I often come across, in LINQ for Entity Framework, a pattern where I add a .Where clause if a string value is specified, like:

IQueryable<Foo> query = Foos.AsQueryable()
if (!string.IsNullOrWhitespace(nameFilter)) query = query.Where(x => x.Name == name);
if (!string.IsNullOrWhitespace(addressFilter) != null) query = query.Where(x => x.Address == addressFilter );
if (!string.IsNullOrWhitespace(cityFilter) != null) query = query.Where(x => x.City == cityFilter );
// ...

I wanted to clean this up and avoid repeating the filter. I thought I could create an extension method:

public static IQueryable<T> WhereEqualIfSpecified<T>(
    this IQueryable<T> query,
    Expression<Func<T, string>> fieldDelegate,
    string filterValue)
{
    return string.IsNullOrWhiteSpace(filterValue) 
        ? query 
        : query.Where(x => fieldDelegate(x) == filterValue);  // not valid, see question below
}

So that I can instead change my code to:

IQueryable<Foo> query = Foos.AsQueryable()
    .WhereEqualIfSpecified(x => x.Name, nameFilter)
    .WhereEqualIfSpecified(x => x.Address, addressFilter)
    .WhereEqualIfSpecified(x => x.City, cityFilter)
    // ...
;

But I found that, in the WhereEqualIfSpecified method above, fieldDelegate must be compiled to a Func() to be invoked against the entity source, which ruins the point of doing these steps, which would be executed in the database in my original code.

I am missing the last step of how to create a new Expression from fieldDelegate that can do a comparison, rather than just returning the string value. Will this approach work? How do I make the necessary Expression in WhereEqualIfSpecified to allow LINQ-to-Entities to execute it later?

trashr0x
  • 6,457
  • 2
  • 29
  • 39
Patrick Szalapski
  • 8,738
  • 11
  • 67
  • 129

1 Answers1

3

What you're trying to do here is to compose expressions. Expressions, unlike delegates, are a bit tricker to compose. Here is one implementation of how to compose expressions. Once you have that Compose method you can write your extension method as:

public static IQueryable<T> WhereEqualIfSpecified<T>(
    this IQueryable<T> query,
    Expression<Func<T, string>> fieldExpression,
    string filterValue)
{
    return string.IsNullOrWhiteSpace(filterValue) 
        ? query 
        : query.Where(fieldExpression.Compose(value => value == filterValue);
}
Community
  • 1
  • 1
Servy
  • 202,030
  • 26
  • 332
  • 449