[英]Entity Framework Core 2.2 orderby evaluated locally
I have this semi-complex query that counts the most voted user post of the last 7 days: 我有这个半复杂的查询,该查询计算最近7天获得投票最多的用户帖子:
var fromDate = dateTimeService.Now.Add(-interval);
var votedPosts =
from vote in dbContext.Votes
join post in dbContext.Posts on vote.PostId equals post.PostId
group new {vote.Sign, post.PostId} by post.PostId
into postVotes
select new {
PostId = postVotes.Key,
TotalRating = postVotes.Sum(pv => pv.Sign)
};
var bestPost = (
from post in dbContext.Posts
join votedPost in votedPosts on post.PostId equals votedPost.PostId
join room in dbContext.Rooms on post.RoomId equals room.RoomId
join game in dbContext.Modules on room.ModuleId equals game.ModuleId
where room.RoomAccess == RoomAccessType.Open && post.CreateDate > fromDate
orderby votedPost.TotalRating descending,
post.CreateDate descending
select new BestPost
{
UserId = post.UserId,
ModuleId = game.ModuleId,
ModuleTitle = game.Title,
PostId = post.PostId,
PostText = post.Text,
PostCommentary = post.Commentary,
PostCreateDate = post.CreateDate,
TotalRating = bestPost.TotalRating
}).FirstOrDefault();
What I try to do here is to group user votes by PostId
, sum the evaluations of their votes by field Sign
(can be -1, 0 or 1), then join it with some additional data like game Id/Title and post texts, filter non-public or too old posts, then order it by rank and then by create date, then map it onto DTO and return the very first result if present. 我在这里尝试做的是将用户投票按PostId
,通过按字段Sign
(可以是-1、0或1)对用户投票的评估求和,然后将其与一些其他数据(例如游戏ID /标题和发布文本)结合起来,过滤非公开或过旧的帖子,然后按等级排序,然后按创建日期排序,然后将其映射到DTO并返回第一个结果(如果有)。
All the fields here are simple basic types: the Vote.Sign
is int
, Post.CreateDate
is DateTime
, all the *Id
are Guid
and Text/Title/Commentary
are string
. 这里的所有字段都是简单的基本类型: Vote.Sign
是int
, Post.CreateDate
是DateTime
,所有*Id
是Guid
而Text/Title/Commentary
是string
。
I get the warning: 我得到警告:
warn: Microsoft.EntityFrameworkCore.Query[20500] 警告:Microsoft.EntityFrameworkCore.Query [20500]
The LINQ expression 'orderby [bestPost].TotalRating desc' could not be translated and will be evaluated locally. LINQ表达式'orderby [bestPost] .TotalRating desc'无法翻译,将在本地进行评估。
warn: Microsoft.EntityFrameworkCore.Query[20500] 警告:Microsoft.EntityFrameworkCore.Query [20500]
The LINQ expression 'FirstOrDefault()' could not be translated and will be evaluated locally. LINQ表达式“ FirstOrDefault()”无法翻译,将在本地进行评估。
If I remove the sort by TotalRating
and only leave the CreateDate
sorting, it works fine, creates proper LIMIT
request. 如果我通过TotalRating
删除排序,而只保留CreateDate
排序,则它可以正常工作,并创建适当的LIMIT
请求。 But with TotalRating
the query looks like this: 但是使用TotalRating
,查询看起来像这样:
SELECT
t."PostId", t."TotalRating", post."CreateDate" AS "PostCreateDate",
post."UserId", game."ModuleId", game."Title" AS "ModuleTitle",
post."PostId" AS "PostId0", post."Text" AS "PostText",
post."Commentary" AS "PostCommentary"
FROM
"Posts" AS post
INNER JOIN
(SELECT
post0."PostId", SUM(vote."Sign")::INT AS "TotalRating"
FROM
"Votes" AS vote
INNER JOIN
"Posts" AS post0 ON vote."PostId" = post0."PostId"
GROUP BY
post0."PostId") AS t ON post."PostId" = t."PostId"
INNER JOIN
"Rooms" AS room ON post."RoomId" = room."RoomId"
INNER JOIN
"Modules" AS game ON room."ModuleId" = game."ModuleId"
WHERE
(room."RoomAccess" = 0) AND (post."CreateDate" > @__fromDate_0)
And it looks pretty bad to be calculated in dotnet runtime. 在dotnet运行时中进行计算似乎很糟糕。
I tried to wrap the result in another select from
, but it didn't help. 我尝试将结果包装到的另一个select from
,但没有帮助。 I also cannot do the group by on all the columns because then I won't be able to aggregate things like ModuleId
because EF Core 2.2 does not support the group.FirstOrDefault
things and PostgreSQL does not support max(uuid)
(otherwise I could use group.Max(g => g.ModuleId)
). 我也不能对所有列进行分组,因为那样我将无法聚合ModuleId
类的ModuleId
因为EF Core 2.2不支持该组group.FirstOrDefault
和PostgreSQL不支持max(uuid)
(否则我可以使用group.Max(g => g.ModuleId)
)。
What am I doing wrong? 我究竟做错了什么?
What happens if you combine the gist of votedPosts
into the query so you don't duplicate the join
on posts
? 如果你结合的要点,会发生什么votedPosts
到查询,所以你不要重复join
上posts
?
var bestPost = (
from post in dbContext.Posts
join vote in dbContext.Votes on post.PostId equals vote.PostId into votej
let voteTotalRating = votej.Sum(pv => pv.Sign)
join room in dbContext.Rooms on post.RoomId equals room.RoomId
join game in dbContext.Modules on room.ModuleId equals game.ModuleId
where room.RoomAccess == RoomAccessType.Open && post.CreateDate > fromDate
orderby voteTotalRating descending,
post.CreateDate descending
select new BestPost {
UserId = post.UserId,
ModuleId = game.ModuleId,
ModuleTitle = game.Title,
PostId = post.PostId,
PostText = post.Text,
PostCommentary = post.Commentary,
PostCreateDate = post.CreateDate,
TotalRating = voteTotalRating
}).FirstOrDefault();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.