【问题标题】:linq to sql syntax different but should get the same resultslinq to sql 语法不同但应该得到相同的结果
【发布时间】:2010-01-14 04:21:55
【问题描述】:

我正在玩弄表达式树和各种 Linq 语法。我写了以下内容:

using (NorthwindDataContext DB = new NorthwindDataContext())
        {
            DataLoadOptions dlo = new DataLoadOptions();

            // Version 1
            dlo.AssociateWith<Customer>(c => c.Orders.Where(o => o.OrderID < 10700).Select(o => o)); 

            // Version 2
            dlo.AssociateWith<Customer>(c => from o in c.Orders
                                             where o.OrderID < 10700
                                             select o);
        }

版本 1 方法返回一个错误,提示“子查询不支持运算符 'Select'。”

虽然第 2 版运行良好。据我了解,我正在写完全相同的东西,但一个是“点”符号语法,另一个是查询表达式语法。

我在这里遗漏了什么吗?为什么一个错误而不是另一个“如果”它们实际上是同一个查询?

【问题讨论】:

    标签: c# linq linq-to-sql


    【解决方案1】:

    为了扩展 Daniel 的答案,select o 被称为退化查询表达式 - 它已被 C# 编译器删除。所以你的查询被翻译成:

    c.Orders.Where(o => o.OrderID < 10700)
    

    请注意,如果没有where 子句,编译器仍然包含Select 调用,因此:

    from o in c.Orders
    select o
    

    被翻译成

    c.Orders.Select(o => o)
    

    来自语言规范的第 7.15.2.3 节:

    退化查询表达式是一个 简单地选择元素 来源。后期阶段 翻译消除了退化的查询 由其他翻译步骤引入 通过用它们的来源替换它们。 然而,重要的是要确保 查询表达式的结果是 绝不是源对象本身,因为 这将揭示类型和 客户端的来源身份 的查询。因此这一步 保护编写的退化查询 通过显式直接在源代码中 在源上调用Select。这是 然后到Select的实现者 和其他查询运算符,以确保 这些方法永远不会返回 源对象本身。

    【讨论】:

    • 感谢 Jon 的回答和出色的解释。
    【解决方案2】:

    您的查询中不需要.Select(o =&gt; o)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      • 2019-01-30
      • 2018-01-11
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      相关资源
      最近更新 更多