2013-12-20 22 views
3

她是我的情况,其中枚举值存储在数据库字符串。虽然检索我得到一个异常,试图将字符串转换为enum使用基类为EnumStringType的mytype。处理异常时进行枚举值不匹配字符串值

这里是我得到的错误:

NHibernate.HibernateException : Can't Parse Enum4 as MyEnum 

例如:从数据库里的值是:“Enum4”

有效枚举值中为每个MyEnum的代码是:

Enum1 Enum2 Enum3

不知怎的,Enum4在代码容纳之前在Db中引入他改变了。 (我知道疯狂的事情发生)

例外的情况是正常的,因为我的枚举没有这个值来自数据库。但我不希望用户得到异常。相反,默认为第一个值。 (我同意这在某些情况下是不行的,但是它可以防止在我的情况下更严重的异常)

如果我没错,GetInstance是将字符串转换为枚举的方法。是否有某种TryGetXXXX来解决这个问题或者如何解决这个问题?

谢谢你的时间!

这里是枚举代码我摆弄来解决这个问题:

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)) 
    { 

    } 
} 

回答

3

尝试在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;  
    } 
} 
+0

这是它。我只需要改变像Enum.TryParse((字符串)代码,真,出instanceValue); – isakavis

+0

你知道你也可以只更新根据表并只设置了所有“Enum4”值“Enum1”。 –

+0

我需要这个代码为Enum4做将会是有效的。这只是导致此问题的过渡时间。覆盖可以在基类中完成吗? – isakavis

0

我遇到了同样的问题,今天和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>