2 years ago
#376321
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