4

(使用实体框架)

当我写:

IEnumerable<string> q = customers /*EF entity*/
.Select (c => c.Name.ToUpper())
.OrderBy (n => n)

c# 编译器知道如何生成表达式树,然后 sql 执行:

SELECT UPPER (Name) FROM Customer ORDER BY UPPER (Name)

还要注意该order by条款

我看到了这个链接

他写了 :

IEnumerable<employee> emp = 
         dc.Employees.Where(x => x.Desc.StartsWith("soft"));
emp = emp.Take(1);

在调查了他看到的最终查询后:

SELECT [t0].[Id], [t0].[Name], [t0].[Address], [t0].[Desc] AS [Desc]
FROM [dbo].[Employee] AS [t0]
WHERE [t0].[Desc] LIKE @p0

注意没有 top条款

这是为什么 ?

Take(x)应该添加到查询中?

会这样写:

IEnumerable<employee> emp = 
         (dc.Employees.Where(x => x.Desc.StartsWith("soft"))).Take(1);

将 TOP 子句添加到发送到 SQL 的查询中?

这是怎么回事?

(我已经知道这take不是延期执行)

4

2 回答 2

9

如果您添加Take(1)到第一个表达式,它将是 on IQueryable<T>,因此添加到 SQL。但是由于您转换IQueryable<T>IEnumerable<T>,Take(1)是在内存中完成的:IEnumerable<T>有一个同名的Take()扩展方法,并且据编译器所知,empis IEnumerable<T>, not IQueryable<T>,所以内存版本被调用。

于 2012-06-22T13:36:30.350 回答
5

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

emp 的编译时类型是IEnumerable<employee>(因为它被显式声明为 one),所以编译器选择Enumerable.Take而不是Queryable.Take,它不执行任何查询翻译。

如果您很懒惰并且只是使用var而不是类型名称:

var emp = dc.Employees.Where(x => x.Desc.StartsWith("soft"));
emp = emp.Take(1);

it would have worked, because the compiler would have picked IQueryable<employee> for emp (because the expression you initialize it with is of that type), and thus Queryable.Take for the second call.

于 2012-06-22T13:45:09.240 回答