Please note: everything is after ToList() and IQueryable<T> not included, but on IEnumerable<T> . Because of this, there is no need to create expression trees. Of course, this is not something that is interpreted by EF or similar.
If you look at the code generated by the compiler for your original query, you will see that it only generates expression trees until the first ToList call.
Example:
The following code:
var query = new List<int>().AsQueryable(); query.Where(x => x > 0).ToList().FirstOrDefault(x => x > 10);
Translated by the compiler to this:
IQueryable<int> query = new List<int>().AsQueryable<int>(); IQueryable<int> arg_4D_0 = query; ParameterExpression parameterExpression = Expression.Parameter(typeof(int), "x"); arg_4D_0.Where(Expression.Lambda<Func<int, bool>>(Expression.GreaterThan(parameterExpression, Expression.Constant(0, typeof(int))), new ParameterExpression[] { parameterExpression })).ToList<int>().FirstOrDefault((int x) => x > 10);
Notice how it generates expressions for everyone before ToList . Everything after, including the usual calls to extension methods.
If you don't imitate this in your code, you are actually sending an Enumerable.ToList call to the LINQ provider, which then tries to convert to SQL and fail.
Daniel Hilgarth
source share