使用自定义 SqlMapper.ITypeHandler 将枚举映射到字符串列 - Dapper
Mapping Enum to string column with custom SqlMapper.ITypeHandler - Dapper
我有大量 PL/SQL 存储过程,其中 return 列的单个字符串表示固定范围内的某种状态值。在我正在处理的项目中,这些列已被 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()
代码运行时,我收到一条错误消息,指出无法转换值 'A' - 错误是从 Enum.Parse 抛出,表明 Dapper 尽管已注册,但实际上根本没有调用我的类型处理程序。有人知道解决这个问题的方法吗?
另一个用户在 Dapper 的 github 网站上报告了这个问题。似乎这是专门围绕 Dapper 中的枚举进行的有意优化,因此我更改了数据库模型而不是尝试更改映射代码。我试图修改 Dapper 本身,但 Dapper 的源代码经过了优化,这是我从未见过的,发出操作码以尽可能高效的方式执行转换——我不想开始尝试如何使那里有变化。
我有大量 PL/SQL 存储过程,其中 return 列的单个字符串表示固定范围内的某种状态值。在我正在处理的项目中,这些列已被 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()
代码运行时,我收到一条错误消息,指出无法转换值 'A' - 错误是从 Enum.Parse 抛出,表明 Dapper 尽管已注册,但实际上根本没有调用我的类型处理程序。有人知道解决这个问题的方法吗?
另一个用户在 Dapper 的 github 网站上报告了这个问题。似乎这是专门围绕 Dapper 中的枚举进行的有意优化,因此我更改了数据库模型而不是尝试更改映射代码。我试图修改 Dapper 本身,但 Dapper 的源代码经过了优化,这是我从未见过的,发出操作码以尽可能高效的方式执行转换——我不想开始尝试如何使那里有变化。