如何在 LINQ 的子查询中使用 GroupBy()?

How to use GroupBy() in subqueries with LINQ?

我有非常简单的 LINQ 表达式

IQueryable<FreeBetDTO> records = UnitOfWork.FreeBets
    .Include(f => f.FreeBetCategories)
    .Include(f => f.FreeBetCards)
    .Where(f => f.FreeBetCards.Any(cards => cards.UserId == request.UserId))
    .Select(f => new FreeBetDTO
    {
        FreeBetId = f.FreeBetId

        LineCategories = f.FreeBetCategories
            .GroupBy(g => new { g.LineCategoryID, g.Title })
            .Select(c =>
                new LineCategoryDTO
                {
                    LineCategoryID = c.Key.LineCategoryID,
                    Title = c.Key.Title
                }).AsEnumerable()
    });

当我执行它时,我发现了错误:

System.InvalidOperationException: Unable to translate collection subquery in projection since it uses 'Distinct' or 'Group By' operations and doesn't project key columns of all of it's tables which are required to generate results on client side. Missing column: t.ID. Either add column(s) to the projection or rewrite query to not use 'GroupBy'/'Distinct' operation.
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.

....

问题就在这里.GroupBy(g => new { g.LineCategoryID, g.Title })。如果我不对记录进行分组,错误就会消失。 我用 GroupBy()Distinct() 尝试了很多案例。但不明白为什么会这样。因为我只需要这样分组。

错误消息说您必须在投影中包含 Id 列。但是你不能用 GroupBy 做到这一点。所以将查询重写为两个步骤(删除不需要的包括):

var rawRecords = UnitOfWork.FreeBets
    .Where(f => f.FreeBetCards.Any(cards => cards.UserId == request.UserId))
    .Select(f => new 
    {
        FreeBetId = f.FreeBetId
        LineCategories = f.FreeBetCategories.Select(c => new { c.Id, c.LineCategoryID, c.Title })
            .ToList()
    })
    .AsEnumerable();

var records = rawRecords
    .Select(f => new FreeBetDTO
    {
        FreeBetId = f.FreeBetId
        LineCategories = f.LineCategories.GroupBy(g => new { g.LineCategoryID, g.Title })
            .Select(c =>
                new LineCategoryDTO
                {
                    LineCategoryID = c.Key.LineCategoryID,
                    Title = c.Key.Title
                })
    });

类似的查询,但更优化:

var query =
    from f in UnitOfWork.FreeBets
    from c in f.FreeBetCards
    where f.FreeBetCards.Any(cards => cards.UserId == request.UserId)
    select new { f.FreeBetId, c.LineCategoryID, c.Title };

query = query.Distinct();

var records = query.AsEnumerable()
    .GroupBy(f => f.FreeBetId)
    .Select(g => new FreeBetDTO
    {
        FreeBetId = g.Key
        LineCategories = g.Select(c =>
                new LineCategoryDTO
                {
                    LineCategoryID = c.LineCategoryID,
                    Title = c.Title
                })
            .AsEnumerable()
    });