我在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]
答案 0 :(得分:2)
OrderBy
信息并不总是保留在Distinct
等其他运算符之间。实体框架没有据我所知记录OrderBy
的传播方式。
之所以有意义,是因为某些运算符的输出顺序不确定。在许多情况下都保留订购的事实为开发人员带来了便利。
将OrderBy
移动到查询的末尾(或至少经过Distinct
)。
答案 1 :(得分:2)
查询差异的原因是Distinct
弄乱了结果顺序。因此,当您先执行OrderBy
然后执行Distinct
时,最好不要执行OrderBy
,因为无论如何该顺序都会丢失。因此,EF可以对其进行优化。
在两者之间调用Take
会导致结果集在语义上有所不同:您首先订购商品,并按该顺序的前1000个商品 ,然后在他们。
查询中可以更改的内容主要取决于要获得的结果。也许您想首先使结果集与众不同,然后按日期排序,最后获取项目数量。根据您的要求,其他选项也可以考虑。