使用自定义SqlMapper.ITypeHandler将Dum映射到字符串列 - Dapper

时间:2015-04-02 12:58:06

标签: c# orm enums dapper

我有大量的PL / SQL存储过程,这些过程返回具有单个字符串的列,这些字符串表示固定范围内的某种状态值。在我正在进行的项目中,这些列已被Dapper映射到域对象上的字符串属性,这些属性管理起来很笨拙且不可靠,所以我想切换到枚举。

如果我使用带有单个字符名称的枚举,例如enum Foo {A, P},我非常确定Dapper会正确映射它们但我不想要这样,我希望枚举带有描述性标签,如下所示:

enum Foo {
    [StringValue("A")]
    Active,
    [StringValue("P")]
    Proposed
}

在上面的例子中,StringValueAttribute是一个自定义属性,我可以使用反射将"A"转换为Foo.Active,这很好 - 除了我需要Dapper为我执行转换逻辑。我写了一个自定义类型处理程序来执行此操作:

public class EnumTypeHandler<T> : SqlMapper.TypeHandler<T>
{
    public override T Parse(object value)
    {
        if (value == null || value is DBNull) { return default(T); }
        return EnumHelper.FromStringValue<T>(value.ToString());
    }

    public override void SetValue(IDbDataParameter parameter, T value)
    {
        parameter.DbType = DbType.String;
        parameter.Value = EnumHelper.GetStringValue(value as Enum);
    }
}

//Usage:
SqlMapper.AddTypeHandler(typeof(Foo),
    (SqlMapper.ITypeHandler)Activator.CreateInstance(typeof(EnumTypeHandler<>).MakeGenericType(typeof(Foo)));

使用SqlMapper.AddTypeHandler()进行注册似乎运行正常,但是当我的DbConnection.Query()代码运行时,我收到错误消息,说明值为&#39; A&#39;无法转换 - 错误是从Enum.Parse抛出的,这表明Dapper实际上并没有实际调用我的类型处理程序,尽管它已被注册。有没有人知道解决这个问题?

1 个答案:

答案 0 :(得分:1)

另一位用户在Dapper的github网站上报告了此问题。看起来这是一个专门围绕Dapper枚举的故意优化,所以我改变了我的数据库模型,而不是试图改变映射代码。我看着尝试修改Dapper本身,但Dapper的源代码优化得像我见过的任何东西,发出操作码以最高性能的方式执行转换 - 我不想开始尝试弄清楚如何制作改变了。