EF Core 2.0按其他属性分组

时间:2018-11-14 16:54:36

标签: c# group-by entity-framework-core

我有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表中的其他属性。

我该如何解决?

1 个答案:

答案 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]