5

作为一个非 C# 精明的程序员,我很好奇 LINQ 查询的评估语义,如下所示:

var people = from p in Person
             where p.age < 18
             select p

var otherPeople = from p in people
                  where p.firstName equals "Daniel"
                  select p

假设这Person是一个定义ageandfirstName字段的 ADO 实体,从数据库的角度来看,这会做什么?具体来说,是否people会运行查询以生成内存中的结构,然后由otherPeople查询查询?或者otherPeople只是从查询中提取数据people然后生成一个新的数据库对等查询?那么,如果我遍历这两个查询,会执行多少条 SQL 语句?

4

5 回答 5

12

它们是可组合的。这是可能的,因为 LINQ 查询实际上是表达式(代码即数据),LINQ 提供程序(如 LINQ-to-SQL)可以评估并生成相应的 SQL。

因为 LINQ 查询是延迟评估的(例如,在您迭代元素之前不会执行),所以您显示的代码实际上不会触及数据库。直到您迭代 otherPeople 或人员才会生成并执行 SQL。

于 2008-09-18T01:34:46.627 回答
4
var people = from p in Person
             where p.age < 18
             select p

转换为:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0]
WHERE [t0].[Age] < @p0

@p0 作为 18 发送的位置

var otherPeople = from p in people
                  where p.firstName equals "Daniel"
                  select p

转换为:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0]
WHERE [t0].[FirstName] = @p0

@p0 以“丹尼尔”的身份发送

var morePeople = from p1 in people
                 from p2 in otherPeople
                 where p1.PersonId == p2.PersonId
                 select p1;

转换为:

SELECT [t0].[PersonId], [t0].[Age], [t0].[FirstName]
FROM [dbo].[Person] AS [t0], [dbo].[Person] AS [t1]
WHERE ([t0].[PersonId] = [t1].[PersonId]) AND ([t0].[Age] < @p0) AND ([t1].[FirstName] = @p1)

其中@p0 是 18,@p1 是“丹尼尔”

如有疑问,请在 IQueryable 上调用 ToString() 或将 TextWriter 提供给 DataContext 的 Log 属性。

于 2008-09-18T04:22:04.570 回答
3

是的,生成的查询是组合的。它包括完整的 where 子句。打开 SQL 分析并尝试自己查看。

Linq 通过表达式树做到这一点。第一个 linq 语句产生一个表达式树;它不执行查询。第二个 linq 语句建立在第一个创建的表达式树的基础上。该语句仅在您枚举结果集合时执行。

于 2008-09-18T01:35:16.233 回答
1

peopleotherPeople包含类型的对象IQueryable<Person>

如果您分别对两者进行迭代,它将运行两个查询。如果您只迭代otherPeople,它将运行预期的查询,带有两个 where 子句。

如果您.ToList()继续people并使用List<Person>第二个查询中的返回值而不是人员,它将变为 LINQ-to-Objects 并且不执行任何 SQL。

这种行为称为延迟执行。这意味着在需要之前不会进行任何查询。在执行之前,它们只是被操纵以形成最终查询的表达式树。

于 2008-09-18T01:33:11.700 回答
0

当您尝试访问最终结果时,将执行这两个查询。您可以尝试查看从 DataContext 对象属性生成的原始 SQL。

于 2008-09-18T01:33:54.630 回答