我有大量的PL / SQL存储过程,返回具有单个字符串的列,表示固定范围内的某种状态值。在我正在研究的项目中,这些列已被Dapper映射到域对象上的字符串属性,这些属性管理起来既不方便又不可靠,所以我想切换到枚举。
如果我使用enum Foo {A, P}
这样的单个字符名称的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()
代码运行时,我收到一条错误,指出无法转换值'A' - 从Enum.Parse抛出错误,提示Dapper实际上并没有调用我的类型处理程序,尽管它已被注册。有没有人知道这方面的方法?
另一位用户在Dapper的github网站上报告了这个问题。看起来这是一个专门针对Dapper中枚举的故意优化,所以我改变了我的数据库模型而不是尝试更改映射代码。我看着尝试修改Dapper本身,但是Dapper的源代码优化得像我从未见过的那样,发出操作码以尽可能最高效的方式执行转换 - 我不想开始尝试弄清楚如何制作在那里改变。