Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GroupBy with SelectMany and Take() - The LINQ expression could not be translated #28002

Open
Tracked by #30173
buecherlstefan opened this issue May 11, 2022 · 11 comments

Comments

@buecherlstefan
Copy link

Include your code

public IQueryable<ProductInfoRawData> ListLastInsertedOnesPerApi(int count = 5)
    {
        var query = _repository.Query
                .GroupBy(x => x.ApiName)
                .SelectMany(x => x.Take(count))
            ;

        return query;
    }

Include stack traces

The LINQ expression 'DbSet<ProductInfoRawData>()
    .GroupBy(x => x.ApiName)
    .SelectMany(x => x
        .AsQueryable()
        .Take(__count_0))' could not be translated. 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.
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
   at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.NavigationExpandingExpressionVisitor.Expand(Expression query)
   at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Zollner.ProductService.Logic.Business.ProductInfoWorkflows.ProductInfoServiceApiInformationCollector.<CollectApiInformationAsync>d__6.MoveNext() in C:\Projekte\product-service\ProductInfoWorkflows\ProductInfoServiceApiInformationCollector.cs:line 33

Include provider and version information

EF Core version: 6.0.5
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Windows 10
IDE: Visual Studio 2022 17.1.6

@roji
Copy link
Member

roji commented May 11, 2022

In SQL, GROUP BY requires using an aggregate operator - Count, Max - to reduce the grouped rows. See the docs for more information.

@smitpatel
Copy link
Contributor

You can write like this

var query = _repository.Query
                .GroupBy(x => x.ApiName)
                .Select(g => g.Take(count))
                .SelectMany(x => x)
            ;

@coridrew
Copy link

You can write like this

var query = _repository.Query
                .GroupBy(x => x.ApiName)
                .Select(g => g.Take(count))
                .SelectMany(x => x)
            ;

This fails with this btw:
"error": "System.InvalidOperationException: The LINQ expression 'x => x' could not be translated. 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'.

@gquinn1998
Copy link

I am having exactly the same issues, I am finding the Groupby does not work at all

@Tantol
Copy link

Tantol commented Nov 4, 2022

I stumbled up on the same issue. GroupBy is not working with SelectMany.

@Luk164
Copy link

Luk164 commented Apr 19, 2023

I think I might be having the same issue, did anyone find a workaround yet?

@coridrew
Copy link

I think I might be having the same issue, did anyone find a workaround yet?

I did not.

@buecherlstefan
Copy link
Author

buecherlstefan commented Apr 21, 2023

Workaround for me is to retrieve the data and then SelectMany(), so the expression don't have to be translated to sql

public IEnumerable<ProductInfoRawData> ListLastInsertedOnesPerApi(int count = 5)
    {
        //
        // LISTING 1
        // var query = _repository.Query.GroupBy(x => x.ApiName).SelectMany(x => x.Take(count));
        //

        // LISTING 1 throws The LINQ expression could not be translated
        // FIX: Do it with IEnumerable

        var enumerable = _repository.Query
            .GroupBy(x => x.ApiName)
            .Select(x => x.OrderByDescending(y => y.DateUtc).Take(count))
            .ToList()
            .SelectMany(x => x);

        return enumerable;
    }

@donguyenthanhlan
Copy link

This is my solution. I replace the code just for demo purposes.

_context.Tags
                    .Where(x => x.CreatedBy == request.CreatedBy)
                    .GroupBy(x => x.MeasuredAt)
                    .OrderByDescending(y => y.Key)
                    .Take(5)
                    .Select(x => x.Select(x => new NewModel {
                        Id = x.Id,
                        CreatedAt = x.CreatedAt,
                        CreatedBy = x.CreatedBy,
                        MeasuredAt = x.MeasuredAt,
                        Value = x.Value
                    }))
                    .ToList()
                    .SelectMany(x => x);

@Poltuu
Copy link

Poltuu commented Mar 7, 2024

I'm surprised that @donguyenthanhlan solution works, and specially when the following does not

_context.Tags
                    .Where(x => x.CreatedBy == request.CreatedBy)
                    .GroupBy(x => x.MeasuredAt)
                    .OrderByDescending(y => y.Key)
                    .Take(5)
                    .SelectMany(x => x.Select(x => new NewModel {
                        Id = x.Id,
                        CreatedAt = x.CreatedAt,
                        CreatedBy = x.CreatedBy,
                        MeasuredAt = x.MeasuredAt,
                        Value = x.Value
                    }))
                    .ToList();

Is there any plan/way to support such requests ? They seem pretty regular to me.

@roji
Copy link
Member

roji commented Mar 7, 2024

@Poltuu yeah, we'll likely do a big push on GroupBy functionality - there's a broad set of issues in the implementation that need to be fixed. That's unfortunately unlikely to happen for 9.0 - but I'm hoping we'll do it for 10 at the latest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests