IEnumerable <T>和Take(x)问题?

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不是延迟执行)

das*_*ght 9

如果添加Take(1)到第一个表达式,它将打开IQueryable<T>,从而添加到SQL中.但既然你转换IQueryable<T>IEnumerable<T>,Take(1)是在内存中完成:IEnumerable<T>有一个相同名字的Take()扩展方法,并尽可能编译器知道,empIEnumerable<T>不是IQueryable<T>,所以在内存中的版本被调用.


Bot*_*000 5

扩展方法,例如Take()静态方法,因此它们在编译时解析.

emp的编译时类型是IEnumerable<employee>(因为它被显式声明为一个),因此编译器选择Enumerable.TakeQueryable.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对于第二次调用.