Npgsql 3.0.0 Chokes on Queries with Parameters that have Custom Type Handlers in Dapper 1.42

c# dapper npgsql postgresql

Question

This issue appears to be with something in Npgsql 3.0.0 that changed from under Dapper 1.42. I came to that conclusion since the following code used to work when using Npgsql 2.2.3 with the same version of Dapper:

public struct MyStruct
{
    private readonly int _val;
    public MyStruct(int i) { _val = i; }
    public int MyInt { get { return _val; } }
}



public class MyStructHandler : SqlMapper.TypeHandler<MyStruct>
{
    public override MyStruct Parse(object value)
    {
        if (value is int)
        {
            return new MyStruct((int)value);
        }
        throw new FormatException("Invalid Conversion to MyStruct");
    }

    public override void SetValue(IDbDataParameter parameter, MyStruct value)
    {
        parameter.DbType = DbType.Int32;
        parameter.Value  = value.MyInt;
    }
}



public static int Main()
{
    var myStructHandler = new MyStructHandler();
    SqlMapper.AddTypeHandler(myStructHandler);

    const string query = "SELECT * FROM MyTable WHERE ID = :someID";
    var queryParams = new DynamicParameters();
    queryParams.Add("someID", new MyStruct(3));
    IDbConnection connection = new NpgsqlConnection(connectionString);
    var result = connection.Execute(query, queryParams);
}

When I run the above code, I get an exception with the message:

Problem with query: SELECT * FROM MyTable WHERE ID = :someID
The given key was not present in the dictionary
System.Collections.Generic.KeyNotFoundException : The given key was not present in the dictionary.

I have verified the following:

1) Passing in parameters of built-in types works correctly. E.g., if I change the line queryParams.Add("someID", new MyStruct(3)); to queryParams.Add("someID", 3);, the query returns as expected.
2) MyStructHandler.Parse works correctly when deserializing a field of type MyStruct
3) The parameter name and casing matches between the query and the DynamicParams object
4) MyStructHandler.SetValue is NEVER called prior to throwing the exception

This bug appears to be newly introduced, and only appears to affect classes with custom Dapper handlers. Does anyone know why this stopped working once I upgraded to Npgsql 3.0.0, and more importantly, how to fix it?

-- ADITIONAL INFORMATION --

The exception is thrown in Npgsql.NpgsqlParameter.set_DbType(DbType value), where there is some call to System.Collections.Generic.Dictionary`2.get_Item(TKey key). Again, this used to work in Npgsql 2.2.3, so I am assuming something changed in that code that broke this use-case.

Accepted Answer

This issue has already been reported and fixed, see https://github.com/npgsql/npgsql/issues/694

You can grab an unstable nuget package to resolve this right away (http://www.npgsql.org/install.html), or wait a few more days until we publish Npgsql 3.0.1 with this fix.



Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why