.netcore EF linq-这是一个错误?非常奇怪的行为

时间:2018-09-27 07:53:18

标签: c# entity-framework entity-framework-core

enter image description here我在sql中有两个表。文档和用户。文档与用户有关,我想吸引最近发送文档的用户。

我需要按文档发送日期进行排序,并获得与此文档相关的唯一(独特)用户

这是我的linq查询

var recentClients = documentCaseRepository.Entities
            .Where(docCase => docCase.AssignedByAgentId == WC.UserContext.UserId)
            .OrderByDescending(userWithDate => userWithDate.LastUpdateDate)
            .Take(1000) // I need this because if I comment this line then EF generate completely different sql query. 
            .Select(doc => new { doc.AssignedToClient.Id, doc.AssignedToClient.FirstName, doc.AssignedToClient.LastName })                
            .Distinct()
            .Take(configuration.MaxRecentClientsResults)                
            .ToList();

生成的sql查询为:

SELECT DISTINCT TOP(5) [t].*
FROM (
     SELECT TOP(1000) [docCase.AssignedToClient].[Id]
     FROM [DocumentCase] AS [docCase]
     INNER JOIN [User] AS [docCase.AssignedToClient] 
       ON ([docCase].[AssignedToClientId] = [docCase.AssignedToClient].[Id])
     WHERE [docCase].[AssignedByAgentId] = 3
     ORDER BY [docCase].[LastUpdateDate] DESC
) 
AS [t]

目前,每件事都是正确的。但是如果我删除这一行

.Take(1000) // I need this because...

EF生成了完全不同的查询,例如:

SELECT DISTINCT TOP(5) 
    [docCase.AssignedToClient].[Id]
FROM [DocumentCase] AS [docCase]
INNER JOIN [User] AS [docCase.AssignedToClient] 
    ON ([docCase].[AssignedToClientId] = [docCase.AssignedToClient].[Id])
WHERE [docCase].[AssignedByAgentId] = 3

我的问题是:为什么EF无法生成与众不同的orderby子句和子查询? 这是BUG EF还是我做错了什么?我必须在linq中生成此sql查询()

SELECT DISTINCT TOP 5 [t].*
FROM ( SELECT [docCase.AssignedToClient].[Id]
 FROM [DocumentCase] AS [docCase]
 INNER JOIN [User] AS [docCase.AssignedToClient] 
   ON [docCase].[AssignedToClientId] = [docCase.AssignedToClient].[Id]
 WHERE [docCase].[AssignedByAgentId] = 1
 ORDER BY [docCase].[LastUpdateDate] DESC
) AS [t]

2 个答案:

答案 0 :(得分:2)

OrderBy信息并不总是保留在Distinct等其他运算符之间。实体框架没有据我所知记录OrderBy的传播方式。

之所以有意义,是因为某些运算符的输出顺序不确定。在许多情况下都保留订购的事实为开发人员带来了便利。

OrderBy移动到查询的末尾(或至少经过Distinct)。

答案 1 :(得分:2)

查询差异的原因是Distinct弄乱了结果顺序。因此,当您先执行OrderBy然后执行Distinct时,最好不要执行OrderBy,因为无论如何该顺序都会丢失。因此,EF可以对其进行优化。

在两者之间调用Take会导致结果集在语义上有所不同:您首先订购商品,并按该顺序的前1000个商品 ,然后在他们。

查询中可以更改的内容主要取决于要获得的结果。也许您想首先使结果集与众不同,然后按日期排序,最后获取项目数量。根据您的要求,其他选项也可以考虑。