我有2张桌子:
composer config repositories.packagist.org composer https://repo-eu-uk-1.packagist.org
我需要显示所有用户及其分数的总和,但是我还需要显示用户名。可以按CategoryId进行过滤。
USERS
UserId
Name
Scores (collection of table Scores)
SCORES
UserId
CategoryId
Points
问题是,当我添加
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();
要花很长时间。我不知道如何访问不在GroupBy内或SUM的属性。此示例非常简单,因为我不仅没有Name,而且还没有User表中的其他属性。
我该如何解决?
答案 0 :(得分:3)
这花费了很长时间,因为查询导致了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();
这仍然会产生警告
LINQ表达式'orderby [p] .Points asc'无法翻译,将在本地求值。
,但至少查询已翻译并作为单个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]