我有2张 table :
USERS
UserId
Name
Scores (collection of table Scores)
SCORES
UserId
CategoryId
Points
我需要显示所有用户及其积分的总和,但我还需要显示用户的姓名。它可以通过 CategoryId 过滤或不过滤。
Context.Scores
.Where(p => p.CategoryId == categoryId) * OPTIONAL
.GroupBy(p => p.UserId)
.Select(p => new
{
UserId = p.Key,
Points = p.Sum(s => s.Points),
Name = p.Select(s => s.User.Name).FirstOrDefault()
}).OrderBy(p => p.Points).ToList();
问题是当我添加
Name = p.Select(s => s.User.Name).FirstOrDefault()
需要这么长时间。我不知道如何访问不在 GroupBy 内或者是 SUM 的属性。这个例子非常简单,因为我不仅有 Name,还有 User 表中的其他属性。
我该如何解决这个问题?
最佳答案
它需要很长时间,因为查询导致 client evaluation 。请参阅 Client evaluation performance issues 以及如何使用 Client evaluation logging 来识别相关问题。
如果您真的在使用 EF Core 2.0,那么除了升级到包含改进的 LINQ GroupBy translation 的 v2.1 之外,您无能为力。即使有了它,解决方案也不是直截了当的 - 查询仍然使用客户端评估。但是可以通过将 GroupBy
部分分离为子查询并将其连接到 Users
表以获取所需的附加信息来重写它。
像这样的东西:
var scores = db.Scores.AsQueryable();
// Optional
// scores = scores.Where(p => p.CategoryId == categoryId);
var points = scores
.GroupBy(s => s.UserId)
.Select(g => new
{
UserId = g.Key,
Points = g.Sum(s => s.Points),
});
var result = db.Users
.Join(points, u => u.UserId, p => p.UserId, (u, p) => new
{
u.UserId,
u.Name,
p.Points
})
.OrderBy(p => p.Points)
.ToList();
这仍然会产生警告
但至少查询被翻译并作为单个 SQL 执行:
SELECT [t].[UserId], [t].[Points], [u].[UserId] AS [UserId0], [u].[Name]
FROM [Users] AS [u]
INNER JOIN (
SELECT [s].[UserId], SUM([s].[Points]) AS [Points]
FROM [Scores] AS [s]
GROUP BY [s].[UserId]
) AS [t] ON [u].[UserId] = [t].[UserId]
关于c# - EF Core 2.0 按其他属性分组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53305197/