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

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

Does LINQ-to-SQL Support Composable Queries?

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

1
2
3
4
5
6
7
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是定义agefirstName字段的ADO实体,从数据库的angular来看,这将做什么?具体来说,是否会运行people查询以生成内存结构,然后由otherPeople查询查询该结构?还是otherPeople的构造只是从people中提取有关查询的数据,然后生成一个新的数据库对等查询?那么,如果我遍历这两个查询,将执行多少个SQL语句?


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

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


1
2
3
var people = FROM p IN Person
             WHERE p.age < 18
             SELECT p

翻译为:

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

其中@ p0通过18发送

1
2
3
var otherPeople = FROM p IN people
                  WHERE p.firstName equals"Daniel"
                  SELECT p

翻译为:

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

其中@ p0以" Daniel"的形式发送通过

1
2
3
4
var morePeople = FROM p1 IN people
                 FROM p2 IN otherPeople
                 WHERE p1.PersonId == p2.PersonId
                 SELECT p1;

翻译为:

1
2
3
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属性。


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

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


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

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

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

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


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


推荐阅读