Dapper: Please add support for Nodatime

Created on 28 Oct 2014  Â·  13Comments  Â·  Source: StackExchange/Dapper

Please add support for Nodatime

enhancement

Most helpful comment

@mgravell Npgsql states that

Since 4.0, Npgsql supports type plugins, which are external nuget packages that modify how Npgsql maps PostgreSQL values to CLR types. One of these is the NodaTime plugin, which makes Npgsql read and write NodaTime types. The NodaTime plugin is now the recommended way to interact with PostgreSQL date/time types, and isn't the default only because of the added dependency on the NodaTime library.
https://www.npgsql.org/doc/types/nodatime.html

When using the Npgsql.NodaTime plugin it doesn't allow to use any (.Net) native date and time types, instead only NodaTime types are allowed, what makes @mj1856 Dapper-NodaTime not compatible since it relies in converting Noda types into DateTime/DateTimeOffset.

When using SELECT command Dapper works well, but when setting value to parameters the exception throw new NotSupportedException($"The member {name} of type {type.FullName} cannot be used as a parameter value"); in SqlMapper.cs is raised. In order to make it work with Npgsql.NodaTime I had to implement something like this

public class InstantHandler : SqlMapper.TypeHandler<Instant>
{
    private InstantHandler() { }

    public override void SetValue(IDbDataParameter parameter, Instant value)
    {
        parameter.Value = value;
    }

    // This is not necessary since Npgsql alredy provide the correct typed value
    public override Instant Parse(object value)
    {
        return (Instant)value;
    }
}

Isn't there a better way? maybe handling it in the LookupDbType method returning DbType.Object instead of raising an exception? Thanks.

All 13 comments

And what would support for nodatime _look like_? Genuine question - not meant in a sarcastic way (tone doesn't convey well on the internet).

For example, if you are a nodatime user, it might be possible for you to create a plugin to do this via the "type handler" API, similar to how Dapper.EntityFramework adds support for the EF geography / geometry types. A separate Dapper.Nodatime package / project (referencing dapper) could be added and maintained by anyone. Likewise, it could be added to the main dapper solution, _but_ I would be reluctant to add it to the core library, simply because of dependency explosion, etc.

Your thoughts?

FYI - I am a contributor to Noda Time, and am looking into this. Likely, it will be a Dapper.NodaTime package, as suggested.

Incidentally - I did something similar for RavenDB awhile back.

I'll look forward to it ;p

Sorry for the delay. I've got a good start here.
https://github.com/mj1856/Dapper-NodaTime

Question - does Dapper support complex types? Noda's ZonedDateTime would have to be saved as two separate fields in SQL (datetimeoffset + nvarchar)

Currently: no. It simply hasn't needed it isn't necessarily something I'm
_opposed_ to - it just hasn't been needed so far.
On 5 Dec 2014 06:36, "Matt Johnson" [email protected] wrote:

Sorry for the delay. I've got a good start here.
https://github.com/mj1856/Dapper-NodaTime

Question - does Dapper support complex types? Noda's ZonedDateTime would
have to be saved as two separate fields in SQL (datetimeoffset + nvarchar)

—
Reply to this email directly or view it on GitHub
https://github.com/StackExchange/dapper-dot-net/issues/198#issuecomment-65753017
.

@mj1856 Any update on this? It's been a while, I'm curious what you're doing for a current solution.

Sorry, I haven't had much time to play with it since then. The parts that are finished should work. Feel free to fork and send a PR if you like, or LMK what parts you need next.

I'm struggling to get Dapper to support reading Oracles TimestampTZ to NodeTime.ZonedDateTime. (Writing it went fine using a SqlMapper.TypeHandler)

Do I have to change the Dapper source to make it map TimestampTZ to anything other that System.DateTime when reading ?

@BirgerGro - Good question. I know timestamptz in PostgreSQL doesn't actually store the time zone part. It just uses it in the session, then converts to UTC and stores as UTC. On retrieval, it uses whatever the current session's time zone is. I'm not sure if Oracle has the same behavior or if it actually stores the supplied time zone. I'd have to experiment more.

Would you please open a separate issue so I don't forget? Thanks.
https://github.com/mj1856/Dapper-NodaTime/issues

@mgravell Npgsql states that

Since 4.0, Npgsql supports type plugins, which are external nuget packages that modify how Npgsql maps PostgreSQL values to CLR types. One of these is the NodaTime plugin, which makes Npgsql read and write NodaTime types. The NodaTime plugin is now the recommended way to interact with PostgreSQL date/time types, and isn't the default only because of the added dependency on the NodaTime library.
https://www.npgsql.org/doc/types/nodatime.html

When using the Npgsql.NodaTime plugin it doesn't allow to use any (.Net) native date and time types, instead only NodaTime types are allowed, what makes @mj1856 Dapper-NodaTime not compatible since it relies in converting Noda types into DateTime/DateTimeOffset.

When using SELECT command Dapper works well, but when setting value to parameters the exception throw new NotSupportedException($"The member {name} of type {type.FullName} cannot be used as a parameter value"); in SqlMapper.cs is raised. In order to make it work with Npgsql.NodaTime I had to implement something like this

public class InstantHandler : SqlMapper.TypeHandler<Instant>
{
    private InstantHandler() { }

    public override void SetValue(IDbDataParameter parameter, Instant value)
    {
        parameter.Value = value;
    }

    // This is not necessary since Npgsql alredy provide the correct typed value
    public override Instant Parse(object value)
    {
        return (Instant)value;
    }
}

Isn't there a better way? maybe handling it in the LookupDbType method returning DbType.Object instead of raising an exception? Thanks.

Isn't there a better way? maybe handling it in the LookupDbType method returning DbType.Object instead of raising an exception? Thanks.

Note that if you are using the Npgsql.NodaTime plugin you can tell Dapper to pass the types through as is and let the plugin deal with them like this:

        SqlMapper.AddTypeMap(typeof(Instant), DbType.DateTime2);

I'm not sure how you'd add that logic to Dapper itself without the external dependency, but you could do it with a another package I guess.

I note there is a special case in there for the LINQ binary type, but I assuming we probably don't want to encourage that style of code?

https://github.com/StackExchange/Dapper/blob/e47d819d4e3be933af97bde6b1b6f4f8c41fa534/Dapper/SqlMapper.cs#L327

Was this page helpful?
0 / 5 - 0 ratings

Related issues

silkfire picture silkfire  Â·  4Comments

amanguptamindtree picture amanguptamindtree  Â·  4Comments

scorgatelli picture scorgatelli  Â·  5Comments

CrescentFresh picture CrescentFresh  Â·  4Comments

huobazi picture huobazi  Â·  4Comments