作为一名非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
是定义age
和firstName
字段的ADO实体,从数据库的角度来看,这会做什么?具体来说,是否运行people
查询以生成内存结构,然后由otherPeople
查询查询?或者otherPeople
的构造是否仅仅从people
提取有关查询的数据,然后生成新的数据库对等查询?那么,如果我迭代这两个查询,那么将执行多少个SQL语句?
答案 0 :(得分:12)
它们是可组合的。这是可能的,因为LINQ查询实际上是表达式(代码作为数据),LINQ提供程序(如LINQ-to-SQL)可以评估并生成相应的SQL。
因为LINQ查询被懒惰地评估(例如,在迭代元素之前不会执行),所以您显示的代码实际上不会触及数据库。直到你遍历其他人或者人们才会生成并执行SQL。
答案 1 :(得分:3)
是的,结果查询是由组成的。它包括完整的where子句。打开SQL分析并尝试自己查看。
Linq通过表达式树来做到这一点。第一个linq语句生成一个表达式树;它不执行查询。第二个linq语句建立在第一个创建的表达式树上。只有在枚举结果集合时才会执行该语句。
答案 2 :(得分:3)
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作为“Daniel”
发送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是“Daniel”
如有疑问,请调用IQueryable上的ToString()或将TextWriter提供给DataContext的Log属性。
答案 3 :(得分:1)
people
和otherPeople
包含IQueryable<Person>
类型的对象。
如果你分别迭代它们,它会运行两个查询。
如果只迭代otherPeople
,它将运行预期的查询,并带有两个where子句。
如果您在.ToList()
上执行people
并在第二个查询中使用返回的List<Person>
而不是人,则它将成为LINQ到对象,并且不会执行任何SQL。
此行为称为延迟执行。意味着在需要之前不会进行任何查询。在执行之前,它们只是被操纵以形成最终查询的表达式树。
答案 4 :(得分:0)
当您尝试访问最终结果时,这两个查询都将执行。您可以尝试查看从DataContext对象属性生成的原始SQL。