.netcore EF linq - это БАГ?Очень странное поведение - PullRequest
0 голосов
/ 27 сентября 2018

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 и подзапрос с различными?Это ошибка 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 голосов
/ 27 сентября 2018

Причина различий в запросах заключается в том, что Distinct портит порядок результатов.Поэтому, когда вы сначала выполняете OrderBy, а затем Distinct, вы просто не можете выполнить OrderBy, потому что этот ордер в любом случае потерян.Таким образом, EF может просто оптимизировать его.

Вызов Take между ними приводит к семантическому различию набора результатов: сначала вы заказываете элементы, берете первые 1000 элементов этого порядка изатем позвоните им Distinct.

То, что вы можете изменить в своем запросе, зависит главным образом от результата, которого вы хотите достичь.Может быть, вы хотите сначала сделать результирующий набор отличным, а затем упорядочить по дате и, наконец, взять количество элементов.Другие варианты также возможны в зависимости от ваших требований.

0 голосов
/ 27 сентября 2018

OrderBy информация не всегда сохраняется в других операторах, таких как Distinct.Entity Framework не документирует (насколько мне известно), как именно распространяется OrderBy.

Этот вид имеет смысл, поскольку некоторые операторы имеют неопределенный порядок вывода.Тот факт, что порядок сохраняется во многих ситуациях, удобен для разработчика.

Переместите OrderBy в конец запроса (или, по крайней мере, после Distinct).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...