TypeHandler doesn't seem to be called

2020-07-09 03:03发布

问题:

The short version

SqlMapper.Query<T> seems to ignore my registered TypeHandler<T>

The long version

Here's a simple query:

SELECT 'Foo' AS CategoryName, 200 AS CategoryRating

...and here's two POCOs:

public class RatingValue
{
    public Int32 Value { get; set; }
    // ... some other properties etc ...
}

public class MyResult
{
    public String CategoryName { get; set; }
    public RatingValue CategoryRating { get; set; }
}

I've created a new TypeHandler implementation which should turn that CategoryRating Int32 into a RatingValue object:

public class RatingValueHandler: SqlMapper.TypeHandler<RatingValue>
{
    public override RatingValue Parse(object value)
    {
        if (value is Int32)
            return new RatingValue() { Value = (Int32)value };

        throw new FormatException("Invalid conversion to RatingValue");
    }

    public override void SetValue(System.Data.IDbDataParameter parameter, RatingValue value)
    {
        // ... null, range checks etc ...
        parameter.DbType = System.Data.DbType.Int32;
        parameter.Value = Int32.Parse(value.Value);
    }
}

Now, before running my query I'm adding my new handler like this:

SqlMapper.AddTypeHandler<RatingValue>(new RatingValueHandler());

However, when I run this:

c.Query<MyResult>("SELECT 'Foo' AS CategoryName, 200 AS CategoryRating");

I get an exception from Dapper - it couldn't parse the results in column 1. I expected Dapper to fire my custom type handler!

I think I'm missing something very, very obvious. Please tell me how silly I am!

回答1:

It isn't you being silly; it is me; the following now pass locally (pushed to github); will deploy to NuGet soon now available on NuGet in v1.27 and above:

public void SO24740733_TestCustomValueHandler()
{
    Dapper.SqlMapper.AddTypeHandler(RatingValueHandler.Default);
    var foo = connection.Query<MyResult>(
        "SELECT 'Foo' AS CategoryName, 200 AS CategoryRating").Single();

    foo.CategoryName.IsEqualTo("Foo");
    foo.CategoryRating.Value.IsEqualTo(200);
}

public void SO24740733_TestCustomValueSingleColumn()
{
    Dapper.SqlMapper.AddTypeHandler(RatingValueHandler.Default);
    var foo = connection.Query<RatingValue>(
        "SELECT 200 AS CategoryRating").Single();

    foo.Value.IsEqualTo(200);
}