她是我的情况,其中枚举值在Db中以字符串形式存储。在检索时,我尝试使用具有基类为EnumStringType的mytype将字符串转换为枚举时遇到异常。
以下是我遇到的错误:
NHibernate.HibernateException : Can't Parse Enum4 as MyEnum
例如:来自数据库的值为:“Enum4”
根据MyEnum代码的有效枚举值为:
Enum1 Enum2 Enum3
在代码适应变化之前,以某种方式在Db中引入了Enum4。 (我知道发生了疯狂的事情)
异常是正常的,因为我的Enum没有来自数据库的这个值。但我不希望用户得到异常。而是默认为第一个值。 (我同意在某些情况下这不行,但它可以防止在我的情况下更严重的异常)
如果我是正确的,GetInstance是执行从字符串到枚举的转换的方法。是否有某种类型的TryGetXXXX可以解决这个问题或如何解决它?
谢谢你的时间!
以下是我正在使用的Enum代码来解决此问题:
public class EnumMappingBase : EnumStringType
{
public EnumMappingBase(Type type)
:base(type)
{
}
public override object GetInstance(object code)
{
return base.GetInstance(code); // Here is where I get the exception.
// I am thinking this is where capturing the exception and defaulting must happen.
// I wish I had a TryGetInstance() here or may be it is there and I am not aware.
}
public override object GetValue(object code)
{
return base.GetValue(code);
}
}
public enum MyEnum
{
Enum1,
Enum2,
Enum3
}
public class MyEnumType : EnumMappingBase
{
public MyEnumType()
: base(typeof(MyEnum))
{
}
}
答案 0 :(得分:4)
尝试在MyEnumType中覆盖GetInstance(),如下所示:
public class MyEnumType : EnumMappingBase
{
public MyEnumType()
: base(typeof(MyEnum))
{}
public override object GetInstance(object code)
{
// Set the desired default value
MyEnum instanceValue = MyEnum.Enum1;
Enum.TryParse(code, true, out instanceValue);
return instanceValue;
}
}
答案 1 :(得分:1)
我今天遇到了同样的问题,并且 kay.herzams 回答帮助创建了这个可以用于任何枚举类型的类。
它更通用,更灵活,所以我想我会为寻找通用解决方案的人分享它。
https://gist.github.com/flopes89/f6c4a079ee3b82c7a1df
using System;
using System.Reflection;
using log4net;
using NHibernate.Type;
/// <summary>
/// This class serves as a helper class to properly en- and decode enum values to/from strings
/// using hibernate. It is a generic class that can be used with any enumeration type and is designed
/// to replace the standard NHibernate.EnumStringType entirely.
///
/// This class should be used whenever an enumeration is consisted via NHibernate, because it has a failsafe
/// decoding of enumeration values from the database by defaulting them back to the given default value
/// when an unknown enumeration value is found in the database, which the default NHibernate.EnumStrinType does not
/// </summary>
/// <typeparam name="T">The enumeration type to use</typeparam>
public class EnumStringType<T> : EnumStringType where T : struct
{
private static ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private T _defaultValue;
/// <summary>
/// Create the type
/// </summary>
/// <param name="defaultValue_">Value to fallback to if an unknown enum value is found</param>
public EnumStringType(T defaultValue_)
: base(typeof(T))
{
_defaultValue = defaultValue_;
}
/// <summary>
/// Get the value of the given code
/// </summary>
/// <param name="code_">The code will be decoded using Enum.TryParse with the Type of this EnumStringType instance</param>
/// <returns>Either the defaultValue of this instance (logged with a warning) or the value of the code</returns>
public override object GetInstance(object code_)
{
T instanceValue = _defaultValue;
if (code_ != null && Enum.TryParse<T>(code_.ToString(), true, out instanceValue)) {
_logger.Debug("Decoded [" + typeof(T) + "] enum value [" + instanceValue + "]");
}
else {
_logger.Warn("Unknown [" + typeof(T) + "] enum value [" + code_ + "] found, defaulting to [" + instanceValue + "]");
}
return instanceValue;
}
}
用法示例:
public enum Permission
{
NULL,
EDIT
}
public class PermissionStringType : EnumStringType<Permission>
{
public PermissionStringType()
: base(Permission.NULL)
{
}
}
映射可以通过以下方式完成:
<set name="Permissions" table="permissions" lazy="true">
<key column="role"/>
<element column="name" type="My.Namespace.PermissionEnumStringType,MyAssemblyName"/>
</set>