Home > database >  NodaTime.Duration not recognized as primitive type by EF Core
NodaTime.Duration not recognized as primitive type by EF Core

Time:11-03

I am using EF Core Npgsql NodaTime. In db configuration I use .UseNodaTime() option and so far it was working ok - all entity props of type NodaTime.Instant are properly mapped to timestamp PG type. However now I wanted to add prop of type NodaTime.Duration which, according to the docs, should map to PG interval:

    public class TestEntity : EntityBase<long>
    {
        public Duration Duration { get; set; }
        public Instant DateTime { get; set; }
    }

When I try to generate new migration for entity above I get following exception:

The property 'TestEntity.Duration' could not be mapped, 
because it is of type 'Duration' which is not a supported primitive type or a valid entity type

So I thought I will just write value converter by myself to map duration to TimeSpan which is default .net type mapped to PG interval:

    public class TestEntityConfiguration : IEntityTypeConfiguration<TestEntity>
    {
        public void Configure(EntityTypeBuilder<TestEntity> builder)
        {
            builder.Property(e => e.Duration).HasConversion(
                duration => duration.ToTimeSpan(),
                timeSpan => Duration.FromTimeSpan(timeSpan)
            );
        }
    }

With custom value converter migration generation succeeded:

CREATE TABLE test_entities (
    id bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
    created_at timestamp NOT NULL,
    updated_at timestamp NOT NULL,
    is_deleted boolean NOT NULL,
    duration interval NOT NULL, -- OK
    date_time timestamp NOT NULL,
    CONSTRAINT pk_test_entities PRIMARY KEY (id)
);

But then when I try to insert new TestEntity with some duration:

            db.TestEntities.Add(new TestEntity()
            {
                Duration = Duration.FromMinutes(30),
                DateTime = DateTime.Now.AsUtc().ToInstant()
            });

            db.SaveChanges();

I get following error:

System.InvalidCastException
Can't write CLR type System.TimeSpan with handler type IntervalHandler

I am not sure what I am missing here - do I need additional (other than .UseNodaTime()) configuration of Npgsql?

Package versions:

        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.9" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.8" />
        <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.9" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.3" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite" Version="3.1.3" />
        <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="3.1.3" />

CodePudding user response:

Support for mapping NodaTime Duration to PostgreSQL interval was only added in version 5 of the provider, you'll have to upgrade in order to use it. Note that the upcoming version 6 (to be released in a couple weeks) substantially improves NodaTime support in various ways - I'd recommend waiting and switching to that.

  • Related