0

I want to call method

 query.Range(item => item.Date, filter.Date);

and have method:

 public static IQueryable<T> Range<T>(this IQueryable<T> query, Func<T, DateTime> func, DateTime range)
    {
       return query.Where(item=> func(item) <= range); // <<-- Error "func(item)"
    }

Error: The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.

How to use function?

Maes
  • 164
  • 2
  • 16
Sequd
  • 91
  • 8

2 Answers2

3

When you write

return query.Where(item => func(item) <= range);

Then lambda item => func(item) <= range is not simple lambda - its converted to Expression<Func<T,bool>>. When you are executing query, EF tries to convert such expressions into SQL code. Unfortunately it does not know how invocation of func should be represented in plain SQL. Thus you see this error. And you cannot use delegate invocations in expressions which you pass to EF.

Workaround: Instead of

query.Range(item => item.Date, filter.Date)

use simple (it's also more readable in this case)

query.Where(item => item.Date <= filter.Date)

UPDATE: You can to build date filter expression manually:

public static IQueryable<T> Range<T>(this IQueryable<T> query,
    Expression<Func<T, DateTime>> func, DateTime range)
{            
    var predicate = 
        Expression.Lambda<Func<T, bool>>(
            Expression.LessThanOrEqual(func.Body, Expression.Constant(range)),
            func.Parameters.Single());

    return query.Where(predicate);
}
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • It is common dll and used generic types – Sequd May 21 '14 at 11:08
  • @Sequd updated answer. Now you can use this extension on any type to filter by date property – Sergey Berezovskiy May 21 '14 at 12:19
  • I just had a very similar case, which i did solve in the same manner, but i had to create manually a new parameter, replace the parameter of the func by the new one and provide it to the generated lambda, otherway i've got an "The parameter xxx was not bound in the specified LINQ to Entities query expression" exception. – Alexander Powolozki Apr 24 '18 at 07:30
1

You can use a more generic approch.

    public IQueryable<T> Filter<T>(Expression<Func<T, bool>> predicate) where T : class
    {
        return db.Set<T>().Where<T>(predicate).AsQueryable<T>();
    }

and call it:

query.Filter<MyClassIWantToFetch>(item => item.Date <= filter.Date)

and dont forget to change MyClassIWantToFetch to the type you want to get.

Daniel Björk
  • 2,475
  • 1
  • 19
  • 26