Search code examples
c#linqentity-frameworklambdalinq-to-entities

Why does .Where() on an IQueryable return a different type based on whether a Lamba or Func<T,Tresult> are passed as parameters


In my Entity Framework Code First project I have a repository object which contains routes

public class EFRepository
{
    ...
    public IQueryable<Route> Routes
    {
        get { return context.Routes; }
    }
   ...
}

If I run

var routes = this.repository.Routes
                  .Where(r => r.DeployedService.IsActive.HasValue 
                   && r.DeployedService.IsActive.Value);

The routes object is of type IQueryable<Route>.

However, if I run

Func<Route, bool> routeIsActive = r => r.DeployedService.IsActive.HasValue 
                                      && r.DeployedService.IsActive.Value;
var routes = this.repository.Routes.Where(routeIsActive);

The routes object in this case is of type IEnumerable<Route>.

I would have thought that they would be evaluated the same but clearly I am wrong. What is the difference between the two statements and why do they return different types.


Solution

  • The method .Where(Expression<Func<Route,bool>>) is defined by IQueryable<Route>. The method .Where(Func<Route,bool>) on the other hand is defined by IEnumerable<Route> and not by IQueryable<Route>. Thus each returns its own type for fluent LINQ method chaining.

    The additional method defined by IQueryable allows the expression tree to be pushed down to the LINQ provider, e.g. LINQ-to-entities, for lazy late evaluation at the provider level where this is possible.