Использование подзапроса для упорядочивания результатов в EF Core - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть простая структура данных форума с ForumPost, представляющим сообщение и ответы.Класс / таблица имеет ParentId, который для сообщений равен NULL и для ответов установлен.Класс / таблица также имеет поле createAt.То, что я пытаюсь сделать, это получить все сообщения в порядке последних созданных, связанных с этим сообщением.Таким образом, если ответы присутствуют, то для порядка следует использовать последний созданный из ответов, в противном случае следует использовать созданный сам пост.

Это довольно легко сделать в SQL, но я не могу найти способ сделать этов EF Core без EF не генерирует SQL, но выполняет orderby в коде.

Итак, простая версия SQL будет выглядеть так:

SELECT [u].[Id], [u].[Content], [u].[CreatedAt], [u].[CreatedById], [u].[ForumId], [u].[ModifiedAt], [u].[ModifiedById], [u].[ParentId], [u].[Sticky], [u].[Title]
FROM [ForumPosts] AS [u]
WHERE ([u].[ForumId] = 1) AND [u].[ParentId] IS NULL
ORDER BY (
    SELECT MAX(tmp.CreatedAt) FROM ForumPosts AS tmp WHERE Id = u.Id OR ParentId = u.Id
) DESC;

Поэтому я попытался перевести это в EF Code и пришелсо следующим:

this.Context.ForumPosts
    .OrderByDescending(u => this.Context.ForumPosts.Where(a => a.Id == u.Id || a.ParentId == u.Id).Max(a => a.CreatedAt))
    .Where(u => u.ForumId == forumId && u.ParentId == null);

Но это приводит к предупреждению, что Макс не может быть переведен и будет выполнен в коде.

Я пробовал несколько других версий (например, используя Select, OrderByи возьмите (1)), но ни один не работал.

Я использую:

  • Microsoft.NETCore.App 2.2.0
  • Microsoft.AspNetCore.App 2.2.0
  • Microsoft.EntityFrameworkCore.Design 2.2.1

Любая помощь по этому вопросу будет принята с благодарностью.

1 Ответ

0 голосов
/ 07 февраля 2019

Ну, я нашел ответ сам.Я не уверен, почему я не пробовал это раньше, но это помогает.Кажется, важно не использовать First(), а FirstOrDefault().В этом сценарии нет смысла, потому что запрос всегда будет возвращать хотя бы одну запись, но с First() EF выполнит упорядочение в коде, а с FirstOrDefault() он сгенерирует относительный нормально SQL-запрос.

this.Context.ForumPosts
    .OrderByDescending(u => this.Context.ForumPosts.Where(a => a.Id == u.Id || a.ParentId == u.Id).OrderByDescending(a => a.CreatedAt).Select(a => a.CreatedAt).FirstOrDefault())
    .Where(u => u.ForumId == forumId && u.ParentId == null);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...