Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dapper column to F# option property

How do I get Dapper to convert data to an F# type with an option property? Simple example:

type SomeType = {
    Count : int option
}

connection.QueryAsync<SomeType>(...)

This throws:

System.InvalidOperationException
    A parameterless default constructor or one matching signature
    (System.Int32 count) is required for SomeType materialization

Using Nullable instead of option works:

type SomeType = {
    Count : Nullable<int>
}

But it's not as desirable for various reasons. For one thing, I have cases where I use string option (because F# doesn't allow null assignments normally, which is great), and Nullable<string> doesn't compile. Is there a way to configure/instruct Dapper to automatically deal with option types? I'd like to avoid using custom mappings every time.

In case it matters, using with Npgsql.

like image 929
Kasey Speakman Avatar asked Dec 24 '22 19:12

Kasey Speakman


1 Answers

I don't think there's any support for adding handlers for open generics, so you'd have to add a type handler for each type you need.

You could define a handler like this:

type OptionHandler<'T>() =
    inherit SqlMapper.TypeHandler<option<'T>>()

    override __.SetValue(param, value) = 
        let valueOrNull = 
            match value with
            | Some x -> box x
            | None -> null

        param.Value <- valueOrNull    

    override __.Parse value =
        if isNull value || value = box DBNull.Value 
        then None
        else Some (value :?> 'T)

And register for the types you need like this:

SqlMapper.AddTypeHandler (OptionHandler<string>())
SqlMapper.AddTypeHandler (OptionHandler<int>())
like image 127
Charles Mager Avatar answered Jan 12 '23 01:01

Charles Mager