1 year ago

#376321

test-img

Linus

Using custom Dapper ITypeHandler for parsing data but not for handling SQL parameters

Assume there is a stored procedure sp_legacy that is not possible to change. The result set contains, among other things, a column called Ids. The column carries a list of integers as JSON. An example result set with three rows could look like this:

Ids
'[1, 2, 3]'
'[2, 3, 4]'
'[-1, 0, 42]'

Dapper is used to execute sp_legacy and map the result to the class LegacyRow:

public class LegacyRow
{
    public IEnumerable<int> { get; set; }
}

To accomplish this a type handler is used:

public class JsonTypeHandler : SqlMapper.ITypeHandler
{
    public object Parse(Type destinationType, object value)
    {
        return JsonConvert.Deserialize((string)value, destinationType);
    }

    public void SetValue(IDbDataParameter parameter, object value)
    {
        throw new NotImplementedException();
    }
}

Which is registered using the IEnumerable<int> type:

SqlMapper.AddTypeHandler(typeof(IEnumerable<int>), new JsonTypeHandler());

This makes it possible to do something like the below. This is desirable, it should be easy to query.

var rows = await DbConnection.QueryAsync<LegacyRow>("sp_legacy", commandType: CommandType.StoredProcedure);

However, this has the nasty unintended side effect that SQL parameters of type IEnumerable<int> will be handled by JsonTypeHandler. For example this will cause a NotImplementedException to be thrown in JsonTypeHandler.SetValue:

IEnumerable<int> ids = ...
await Dapper.ExecuteAsync("select * from foo where Id in @Ids", new { Ids = ids }, CommandType.Text);

What alternatives are there for keeping the automatic deserialization of the Ids column while not modifying the default handling of IEneumerable<int> SQL parameters?

c#

sql

dapper

0 Answers

Your Answer

Accepted video resources