使用子查询对EF Core中的结果进行排序

时间:2019-02-07 10:23:33

标签: entity-framework .net-core

我有一个简单的Forum数据结构,其中ForumPost代表了Post和答案。类/表有一个ParentId,对于帖子,它为NULL,并为答案设置。类/表还具有createdAt字段。 我想做的是按照与该帖子相关的最后一个createdAt的顺序获取所有帖子。因此,如果存在答案,则应使用答案的最新createdBy顺序,否则应使用帖子本身的createdAt。

这在SQL中很容易完成,但是如果没有EF不生成SQL而是在代码中执行orderby,我无法找到在EF Core中实现此目的的方法。

因此,一个简单的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代码,并提出了以下建议:

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);

但这会导致警告,Max无法翻译,将在代码中执行。

我尝试了其他几个版本(例如,使用Select,OrderBy和Take(1)),但没有一个起作用。

我正在使用:

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

对此将提供任何帮助。

1 个答案:

答案 0 :(得分:0)

好吧,我自己找到了答案。我不确定为什么我以前没有尝试过,但是可以解决问题。重要的事情似乎不是使用First(),而是使用FirstOrDefault()。在这种情况下,这是没有意义的,因为查询将始终返回至少一个条目,但是使用First() EF会在代码中进行排序,而使用FirstOrDefault()会生成相对好的SQL查询。 / p>

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);