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

EF.Functions.Sum throws #2569

Closed
aradalvand opened this issue Nov 20, 2022 · 7 comments
Closed

EF.Functions.Sum throws #2569

aradalvand opened this issue Nov 20, 2022 · 7 comments

Comments

@aradalvand
Copy link

aradalvand commented Nov 20, 2022

Here's a simple repro: https://github.com/aradalvand/efcore-pgsql-bug

Let me know if I'm missing something here because this seems very basic.

I used to have a pretty simple expression to get the sum of a related collection's TimeSpan properties:

var course = db.Courses.Select(c => new
{
    TotalDuration = TimeSpan.FromSeconds(c.Videos.Sum(v => v.Duration.TotalSeconds)),
}).FirstOrDefault();

This worked (still does of course), generating the following SQL:

SELECT (
     SELECT COALESCE(sum(date_part('epoch', v."Duration")), 0.0)
     FROM "Videos" AS v
     WHERE c."Id" = v."CourseId")
  FROM "Courses" AS c
  LIMIT 1

Now, in EF7, with the introduction of provider-specific aggregate functions, I wanted to change the code above to use the EF.Functions.Sum method instead — to avoid converting the column into seconds and back:

var course = db.Courses.Select(c => new
{
    TotalDuration = EF.Functions.Sum(c.Videos.Select(v => v.Duration)),
}).FirstOrDefault();

This looks like the most basic usage of this method.
But to my surprise I found out it actually throws:

Unhandled exception. System.InvalidOperationException: The 'Sum' method is not supported because the query has switched to client-evaluation. This usually happens when the arguments to the method cannot be translated to server. Rewrite the query to avoid client evaluation of arguments so that method can be translated to server.
   at Microsoft.EntityFrameworkCore.NpgsqlAggregateDbFunctionsExtensions.Sum(DbFunctions _, IEnumerable`1 input)
   at lambda_method94(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
   at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable`1 source, Boolean& found)
   at lambda_method95(Closure , QueryContext )
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at Program.<Main>$(String[] args) in /home/arad/other/efcore-pgsql-bug/Program.cs:line 3

What's wrong here?!

Thank you in advance.

@roji
Copy link
Member

roji commented Nov 20, 2022

Does it work if the thing inside the Sum is a direct property on c rather than on a related entity (Videos)?

@aradalvand
Copy link
Author

aradalvand commented Nov 20, 2022

@roji Thank you for the response.

EF.Functions.Sum receives an IEnumerable of TimeSpan, as you know. So how would you pass a single property there? Unless the property is an array of TimeSpan itself (I haven't tested that I don't know if it works). But are you saying that's its only use case?

I did provide a very simple repro by the way if that helps.

@aradalvand
Copy link
Author

aradalvand commented Nov 20, 2022

Update: I just tested this:

var course = db.Videos.GroupBy(_ => true).Select(g => new
{
    TotalDuration = EF.Functions.Sum(g.Select(v => v.Duration)),
}).FirstOrDefault();

And it seems to work, so apparently EF.Functions.Sum only supports this specific kind of scenario (i.e. GroupBy), why though? That seems strange to me.

Shouldn't something like EF.Functions.Sum(c.Videos.Select(v => v.Duration)) be possible too?! That's what I was expecting.

@roji
Copy link
Member

roji commented Nov 21, 2022

I'll look into this (but it will probably take some time).

@roji
Copy link
Member

roji commented Nov 25, 2022

Duplicate of dotnet/efcore#29200

@roji roji marked this as a duplicate of dotnet/efcore#29200 Nov 25, 2022
@roji
Copy link
Member

roji commented Nov 25, 2022

Took a deeper look at this, and it's unfortunately a current limitation of EF (dotnet/efcore#29200) - custom aggregate functions can only be used with GroupBy. For now, until this limitation is lifted, rewrite your query via GroupBy as you've done above.

@roji roji closed this as not planned Won't fix, can't repro, duplicate, stale Nov 25, 2022
@roji
Copy link
Member

roji commented Nov 25, 2022

(and please upvote dotnet/efcore#29200!)

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

No branches or pull requests

2 participants