【问题标题】:Does LINQ-to-SQL Support Composable Queries?LINQ-to-SQL 是否支持可组合查询?
【发布时间】:2010-09-10 11:48:12
【问题描述】:

作为一个非 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 是一个定义agefirstName 字段的ADO 实体,那么从数据库的角度来看,这会做什么?具体来说,是否会运行people 查询以生成内存结构,然后由otherPeople 查询查询?或者otherPeople 的构造是否只是从people 中提取有关查询的数据,然后生成一个新的数据库对等查询?那么,如果我对这两个查询进行迭代,会执行多少条 SQL 语句?

【问题讨论】:

    标签: sql linq linq-to-sql code-reuse


    【解决方案1】:

    peopleotherPeople 包含 IQueryable&lt;Person&gt; 类型的对象。

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

    如果您对people 执行.ToList() 并在第二个查询中使用返回的List&lt;Person&gt; 而不是人员,则它变为LINQ-to-Objects 并且不执行任何SQL。

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:
            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() 或为 DataContext 的 Log 属性提供 TextWriter。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-11-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-01-21
              相关资源
              最近更新 更多