Skip to content

Implement sum and avg PG interval #2339

@ponderingexistence

Description

@ponderingexistence

Hey there, thank you immensely for your phenomenal work, it's truly invaluable.

It's not unthinkable to have entity classes that contain properties of type TimeSpan, which are by default mapped to PostgreSQL's interval type.
Now, Postgres supports doing sum on interval columns, like so:

SELECT sum(l.duration)
FROM lessons AS l
WHERE l.course_id = 1000

Nice and simple.
However, currently there seems to be no way to get EF Core and Npgsql to generate a SQL like that for TimeSpan properties.

Consider the following model:

public class Lesson
{
    public int Id { get; set; }
    public string Title { get; set; }
    public TimeSpan Duration { get; set; }
}

If you do

var totalDuration = new TimeSpan(db.Lessons.Sum(l => l.Duration.Ticks));

The following exception will be raised:

Unhandled exception. System.InvalidOperationException: The LINQ expression 'DbSet<Lesson>()
    .Sum(l => l.Duration.Ticks)' 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.QueryableMethodTranslatingExpressionVisitor.<VisitMethodCall>g__CheckTranslated|15_0(ShapedQueryExpression translated, <>c__DisplayClass15_0& )

I think it's reasonable to say that there should be a way (at least maybe with a special function of some sort, similar to the ones in DbFunctions — e.g. NpgqlFunctions.SumInterval(TimeSpan t) or something, I don't know) to trigger a sum on an interval column. Currently, the only workaround I can think of is something like this:

var totalDuration = new TimeSpan(db.Lessons.Select(l => l.Duration).ToList().Sum(t => t.Ticks));

which isn't nice, as it obviously first retrieves the durations of all the lessons, in this example, and then does the calculation on the client-side, as opposed to taking advantage of PostgreSQL's native sum function.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions