LINQ-to-SQL是否支持可组合查询?

时间:2020-03-06 14:19:38  来源:igfitidea点击:

作为一个非精通的程序员,我对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实体,那么从数据库的角度来看这将做什么?具体来说,是否要运行"人员"查询以生成一个内存中的结构,然后由" otherPeople"查询来查询该结构?还是" otherPeople"的构造仅从" people"中提取有关查询的数据,然后产生一个新的数据库对等查询?因此,如果我遍历这两个查询,将执行多少个SQL语句?

解决方案

people和otherPeople包含类型为IQueryable <Person>的对象。

如果我们分别迭代这两个查询,它将运行两个查询。
如果只迭代" otherPeople",它将运行带有两个where子句的预期查询。

如果对people进行.ToList()并在第二个查询中使用返回的List <Person>而不是people,它将成为LINQ-to-Objects,并且不执行任何SQL。

此行为称为延迟执行。这意味着直到需要查询时才进行查询。在执行之前,它们只是表达式树,可以对其进行操作以制定最终查询。

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

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

由于LINQ查询是惰性计算的(例如,直到我们遍历元素时才会执行),因此显示的代码实际上不会涉及数据库。直到我们遍历其他人,否则人们才会生成并执行SQL。

是的,结果查询已组成。它包含完整的where子句。打开SQL性能分析,然后尝试自己看看。

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

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是"丹尼尔"

如有疑问,请在IQueryable上调用ToString()或者将TextWriter赋予DataContext的Log属性。