1 year 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