6
Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

I pass parameter to Where method as follows: f => f.Id > 4. Can I pass a delegate method instead of f.Id > 4?

Rui Jarimba
  • 11,166
  • 11
  • 56
  • 86
Linh
  • 1,024
  • 2
  • 16
  • 28

1 Answers1

14

No.

The Entity Framework needs to be able to see everything that is being attempted.

So if you simply did something like this:

queryable.Where(f => DelegateFunc(f));

Where the definition of DelegateFunc looks like this:

public bool DelegateFunc(Foo foo)
{
   return foo.Id > 4;
}

The Entity Framework has no way of peering inside the delegate, to crack it open and convert it to SQL.

All is not lost though.

If your goal is to re-use common filters etc you can do something like this instead:

public Expression<Func<Foo, bool>> DelegateExpression{
   get{
       Expression<Func<Foo,bool>> expr = f => f.Id > 4;
       return expr;
   }
}

queryable.Where(DelegateExpression);
Alex James
  • 20,874
  • 3
  • 50
  • 49
  • You are wrong, Alex. I pass to Where method as follows: "queryable.Where(f => DelegateFunc);" instead of "queryable.Where(f => DelegateFunc(f));". The statement executed successfully but it returned an Enumerable not Queryable. – Linh Sep 24 '10 at 06:22
  • I beg to differ. Generally when executing a filter you want to convert it to SQL. Getting an IEnumerable proves that you are NOT executing the filter in the database, instead LINQ to objects it taking over, and you are retrieving every record in the database and filtering in memory. Might work okay in testing, but once you have a lot of data it will perform awfully. Essentially you are using EF only to materialize entities, which is an anti-pattern. – Alex James Sep 24 '10 at 14:16
  • Your comment is very useful, Alex. It has shown the defect of performance in my way. Instead of passing a delegate method, I will pass an Expression>, which is returned by a method. In that method I can custom the condition. – Linh Sep 27 '10 at 14:44
  • Alex, why do you know LINQ will take every record in the database and filtering in memory? where did you read article, blog or documentation? – Linh Sep 27 '10 at 14:58
  • I worked on the Entity Framework product team at Microsoft. But more importantly if you don't have an query as an expression there is no way to convert it to SQL. That is why LINQ and expressions was invented. Oh and BTW I think I deserve an accept here! – Alex James Sep 27 '10 at 17:59
  • +1 I wish I had stumbled upon this earlier. I learned it the hard way when I had implemented a RepositoryPattern API with a Where filterCriteria accepted as a parameter - the context.Entity.Where(filterCritera) would load all the records and then perform filtering!! Shocking. Just changed the API to accept an Expression wrapping the filterCriteria and it works as expected... – bhavinb Jan 23 '12 at 06:09
  • Is there a good way to combine these, or do you simply chain them? i.e. so you can use self-documenting names for different parts of an expression and combine them. e.g. if you had expressions `Expression> IsActive` and `Expression> CreatedThisWeek` would the best way to combine them be `queryable.Where(IsActive).Where(CreatedThisWeek)`, or does this if your database had an index on creation date rather than status would this risk poor performance? Also, could you do an `or` instead of an `and` like this? – JohnLBevan Mar 02 '18 at 17:04
  • (for others hitting this thread; asked about multiple expressions here: https://stackoverflow.com/questions/49074642/combine-multiple-linq-expressions) – JohnLBevan Mar 02 '18 at 17:49