LINQ-to-SQL是否支持可组合查询?
作为一个非精通的程序员,我对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属性。