【问题标题】:Why does LINQ-to-Entities put this query in a sub-select?为什么 LINQ-to-Entities 将此查询放在子选择中?
【发布时间】:2012-06-20 23:04:05
【问题描述】:

我有以下 LINQ 查询:

var queryGroups = (from p in db.cl_contact_event
                   select new Groups { inputFileName = p.input_file_name }).Distinct();

运行时转换为以下内容:

SELECT 
[Distinct1].[C1] AS [C1], 
[Distinct1].[input_file_name] AS [input_file_name]
FROM ( SELECT DISTINCT 
       [Extent1].[input_file_name] AS [input_file_name], 
       1 AS [C1]
       FROM [mel].[cl_contact_event] AS [Extent1]
)  AS [Distinct1]

现在我很确定存在子选择的原因是因为我有基本的 LINQ 查询被 () 包围,然后执行 .Distinct() 但我对 LINQ 的了解不够,无法确定这。如果确实如此,有没有办法重组/编码我的查询,以便不会发生子选择?

我知道我可能只是在这里吹毛求疵,但我只是好奇。

【问题讨论】:

  • @DannyVarod linq-to-entities 我相信,因为我使用的是 EF4,所以我正在查询 Sybase 数据库。
  • 在这种情况下,更改您使用的标签并相应地更新问题的标题。
  • 比较 EF 生成的查询计划和您建议的改进之间的查询计划,看看是否有差异。查询优化器非常聪明。

标签: c# linq linq-to-entities sybase


【解决方案1】:

我根本不会担心这种特殊情况。 SQL Server(很可能是任何企业数据库)无论如何都会优化外部 Select 语句。我认为生成此 SQL 语句的原因是因为这是最通用和可重用的语句。根据我的经验,这总是发生在Distinct()

【讨论】:

    【解决方案2】:

    在此我怀疑子查询的实际根本原因是匿名类型构造函数。因为您选择的不是已知实体,而是从其他实体值构造的任意对象,所以 EF 解析器需要确保它可以生成准确的字段集——无论是来自单个表、连接表、计算字段还是其他子查询等。表达式树解析器非常擅长尽可能从 LINQ 查询中编写 SQL 语句,但它并不是无所不知的。它以系统的方式处理查询,这将始终产生正确的结果(从某种意义上说,您得到了您所要求的),但并不总是最佳结果。

    至于重写查询以消除子选择,首先:我没有看到明显的方法可以消除匿名类型并产生正确的结果。不过,更重要的是,我不会打扰。像 Sybase 这样的现代 SQL 服务器非常聪明——通常比开发人员更聪明——并且非常擅长从查询中生成最佳查询计划。除此之外,EF 喜欢子查询,因为它们是自动编写复杂查询的好方法。即使您的 LINQ 查询没有出现使用它们,您也经常会发现它们。试图从查询中消除它们很快就会成为徒劳的练习。

    【讨论】:

    • 感谢您出色而详细的回复。我只是想确定我没有犯任何明显的错误。
    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-29
    相关资源
    最近更新 更多