#1649·Dapper

TypeHandlers not called for parameters extracted from list expansion

Author: benbryant0Created Apr 10, 2021Updated Sep 16, 2026

I've noticed that types with a TypeHandler registered will not have that handler executed if the type is part of a collection that Dapper expands. Here's a test to reproduce this:

csharp
private readonly struct IdentityType
{
    private readonly int _value;

    public IdentityType(int value)
    {
        _value = value;
    }

    public int CompareTo(IdentityType other) => _value.CompareTo(other._value);

    public override int GetHashCode() => _value;

    public override string ToString() => _value.ToString();

    public static explicit operator int(IdentityType d) => d._value;
    public static explicit operator IdentityType(int d) => new(d);
}

private class IdentityTypeHandler : SqlMapper.TypeHandler<IdentityType>
{
    public override IdentityType Parse(object value) => new((int)value);
    public override void SetValue(IDbDataParameter parameter, IdentityType value)
    {
        parameter.DbType = DbType.Int32;
        parameter.Value = (int)value;
    }
}

[Fact]
public void Potato()
{
    SqlMapper.AddTypeHandler(new IdentityTypeHandler());

    var identityList = Enumerable.Range(1, 5)
        .Select(i => new IdentityType(i))
        .ToList();

    var param = new { firstItem = identityList[0], allItems = identityList };
    var result = connection.Query<int?>("SELECT * FROM (VALUES(1)) AS t(Id) WHERE @firstItem IN @allItems;", param)
        .SingleOrDefault();

    Assert.Equal(1, result);
}

I'm not familiar with the code here, but a bit of investigating led me to this line where the type handler would be fetched but not used. I managed to get my test to pass by persisting the handler and using it if it was set; but due to the other branches based on specific types (isString and isDbString), I'm not sure what the correct behaviour should be.. otherwise this would be a PR :D

Forgive me if this is intended and/or there's a different way to do it. I've searched around and couldn't find any information about this.