简体   繁体   English

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

[英].netcore EF linq - this is a BUG? Very strange behavior

在此处输入图片说明 I have two table in sql. 我在sql中有两个表。 Document and User. 文档和用户。 Document have relation to User and I want to get users that I sent document recently. 文档与用户有关,我想获得最近发送文档的用户。

I need to sort by the date document was sent and get unique (distinct) user with relation to this document 我需要按发送文档的日期进行排序,并获得与此文档相关的唯一(不同)用户

This is my linq queries 这是我的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();

and generated sql query is: 生成的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]

Every thing is correct for now. 到目前为止,每件事都是正确的。 But if I delete this line 但是如果我删除这一行

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

EF generated completely different query such as: 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

My question is: why EF not generated orderby clause and subquery with distinct? 我的问题是:为什么EF无法生成与众不同的orderby子句和子查询? This is a BUG EF or I'm doing something wrong? 这是BUG EF还是我做错了什么? And what I must do to generate in linq this sql query () 我必须做些什么才能在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]

OrderBy information not always retained across other operators such as Distinct . OrderBy信息并不总是在其他运营商之间保留,例如Distinct Entity Framework does not document (to my knowledge) how exactly OrderBy is propagated. 实体框架(据我所知)没有记录如何精确传播OrderBy

This kind of makes sense because some operators have undefined output order. 之所以有意义,是因为某些运算符的输出顺序不确定。 The fact that ordering is retained in many situations is a convenience for the developer. 在很多情况下都保留订购的事实为开发人员带来了便利。

Move the OrderBy to the end of the query (or at least past the Distinct ). OrderBy移动到查询的末尾(或至少经过Distinct )。

The reason for the difference in queries is that Distinct messes up result order. 查询差异的原因是Distinct弄乱了结果顺序。 So when you first execute OrderBy and then Distinct , you can just es well not execute OrderBy , because this order is lost anyway. 因此,当您先执行OrderBy然后执行Distinct ,可以很好地不执行OrderBy ,因为无论如何该订单都会丢失。 So EF can just optimize it away. 因此,EF可以对其进行优化。

Calling Take in between causes the result set to be semantically different: You first order the items, take the first 1000 items of that order and then call Distinct on them. 在之间调用Take in会导致结果集在语义上有所不同:您首先对项目进行订购,从该订单中获取前1000个项目然后对它们调用Distinct

What you can change in your query depends mainly on the result you want to achieve. 您可以在查询中更改的内容主要取决于要获得的结果。 Maybe you want to first make the result set distinct then order by date and finally take the amount of items. 也许您想首先使结果集与众不同,然后按日期排序,最后获取项目数量。 Other options are also thinkable based on your requirements. 根据您的要求,其他选项也可以考虑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM