Skip to content

Failed translating LINQ to SQL when using "let" keyword after "group by". #37402

@deadcativan

Description

@deadcativan

Bug description

I wrote a linq using "let" clause to store the subexpression into a range variable "score", in order to use it in the "orderby" and "select".

            var query =
                from watchVideo in DbContext.Set<WatchVideoEntity>().AsNoTracking()
                where watchVideo.CreatedAt >= createdFrom && watchVideo.CreatedAt < createdBefore
                group watchVideo by watchVideo.VideoId into g
                let score = (g.Sum(x => x.CompletionRate) + globalAvgCompletionRate * bayesianAverageConfidence) / (g.Count() + bayesianAverageConfidence)
                where g.Count() >= minWatchCount
                orderby score descending
                select new
                {
                    VideoId = g.Key,
                    Score = score,
                };

It throwed exception :

The LINQ expression 'DbSet()
.Where(watchVideo => watchVideo.CreatedAt >= @createdFrom && watchVideo.CreatedAt < @createdBefore)
.GroupBy(watchVideo => watchVideo.VideoId)
.Select(g => new {
g = g,
score = g
.AsQueryable()
.Sum(x => x.CompletionRate) + @p / (double)(g
.AsQueryable()
.Count() + @bayesianAverageConfidence)
})' could not be translated. Additional information: Translation of 'Select' which contains grouping parameter without composition is not supported. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

But if I rewrote the linq to remove the let clause and use the subexpression directly, it worked.

            var query =
                from watchVideo in DbContext.Set<WatchVideoEntity>().AsNoTracking()
                where watchVideo.CreatedAt >= createdFrom && watchVideo.CreatedAt < createdBefore
                group watchVideo by watchVideo.VideoId into g
                where g.Count() >= minWatchCount
                orderby (g.Sum(x => x.CompletionRate) + globalAvgCompletionRate * bayesianAverageConfidence) / (g.Count() + bayesianAverageConfidence) descending
                select new
                {
                    VideoId = g.Key,
                    Score = (g.Sum(x => x.CompletionRate) + globalAvgCompletionRate * bayesianAverageConfidence) / (g.Count() + bayesianAverageConfidence),
                };

Stack traces


Verbose output


EF Core version

10

Database provider

No response

Target framework

.NET 10

Operating system

No response

IDE

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions