7

我有以下 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 的了解不够,无法确定这一点。如果确实如此,有没有办法重组/编码我的查询,以便不会发生子选择?

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

4

2 回答 2

4

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

于 2012-06-18T22:35:11.940 回答
4

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

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

于 2012-06-18T23:28:00.200 回答