Output IEnumerable <T> and Take (x)?
(using Entity Framework)
when I write:
IEnumerable<string> q = customers /*EF entity*/ .Select (c => c.Name.ToUpper()) .OrderBy (n => n) The C # compiler knows how to emit expression trees, which in turn are executed by sql:
SELECT UPPER (Name) FROM Customer ORDER BY UPPER (Name) note also that there is an order by clause
but
I saw this link :
He wrote:
IEnumerable<employee> emp = dc.Employees.Where(x => x.Desc.StartsWith("soft")); emp = emp.Take(1); after examining the final request that he saw:
SELECT [t0].[Id], [t0].[Name], [t0].[Address], [t0].[Desc] AS [Desc] FROM [dbo].[Employee] AS [t0] WHERE [t0].[Desc] LIKE @p0 Please note that there is no top offer
why?
shouldn't add Take(x) to the request?
will write it as follows:
IEnumerable<employee> emp = (dc.Employees.Where(x => x.Desc.StartsWith("soft"))).Take(1); Would add a TOP clause to the query sent by SQL?
what's going on here?
(I already know that take not deferred execution)
Extension methods, such as Take() , are static methods, and therefore they are allowed at compile time.
The compile-time type emp is IEnumerable<employee> (because it is explicitly declared as one), so the compiler chooses Enumerable.Take instead of Queryable.Take , which does not perform any query translation.
If you were lazy and just used var instead of a type name:
var emp = dc.Employees.Where(x => x.Desc.StartsWith("soft")); emp = emp.Take(1); this would work because the compiler would IQueryable<employee> for emp (because the expression you are initializing with this type), and thus Queryable.Take for the second call.
If you added Take(1) to the first expression, it will be on IQueryable<T> and thus added to SQL. But since you converted IQueryable<T> to IEnumerable<T> , Take(1) is executed in memory: IEnumerable<T> has an extension method Take() with the same name and, as far as the compiler knows, emp is IEnumerable<T> , and not IQueryable<T> , so the version in memory is called.