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.