Roy*_*mir 4 .net c# linq entity-framework .net-4.0
(使用实体框架)
我写的时候:
IEnumerable<string> q = customers /*EF entity*/
.Select (c => c.Name.ToUpper())
.OrderBy (n => n)
Run Code Online (Sandbox Code Playgroud)
c#编译器知道如何发出表达式树,而sql又执行:
SELECT UPPER (Name) FROM Customer ORDER BY UPPER (Name)
Run Code Online (Sandbox Code Playgroud)
另请注意该order by条款
但
我看到这个链接 :
他写了 :
IEnumerable<employee> emp =
dc.Employees.Where(x => x.Desc.StartsWith("soft"));
emp = emp.Take(1);
Run Code Online (Sandbox Code Playgroud)
在调查最终查询后,他看到:
SELECT [t0].[Id], [t0].[Name], [t0].[Address], [t0].[Desc] AS [Desc]
FROM [dbo].[Employee] AS [t0]
WHERE [t0].[Desc] LIKE @p0
Run Code Online (Sandbox Code Playgroud)
注意没有 top条款
这是为什么 ?
不Take(x)应该添加到查询中?
会像这样写:
IEnumerable<employee> emp =
(dc.Employees.Where(x => x.Desc.StartsWith("soft"))).Take(1);
Run Code Online (Sandbox Code Playgroud)
会将TOP子句添加到发送到SQL的查询中吗?
这是怎么回事?
(我已经知道这take不是延迟执行)
如果添加Take(1)到第一个表达式,它将打开IQueryable<T>,从而添加到SQL中.但既然你转换IQueryable<T>到IEnumerable<T>,Take(1)是在内存中完成:IEnumerable<T>有一个相同名字的Take()扩展方法,并尽可能编译器知道,emp是IEnumerable<T>不是IQueryable<T>,所以在内存中的版本被调用.
扩展方法,例如Take()静态方法,因此它们在编译时解析.
emp的编译时类型是IEnumerable<employee>(因为它被显式声明为一个),因此编译器选择Enumerable.Take而Queryable.Take不是执行任何查询转换.
如果你一直懒惰而只是使用var而不是类型名称:
var emp = dc.Employees.Where(x => x.Desc.StartsWith("soft"));
emp = emp.Take(1);
Run Code Online (Sandbox Code Playgroud)
它会起作用,因为编译器会选择IQueryable<employee>emp(因为你初始化它的表达式是那种类型),因此Queryable.Take对于第二次调用.