在Nhibernate中使用枚举

我们会经常有这种需求:把一个字段映射成一个枚举。

于是Nhibernate提供了这种能力,在mapping中不指定type,让NH自己推断就好。于是今天收工(喂。。。

呃。。。继续说。印象中,按照上述方法,NH会往你的char或者varchar字段中存入枚举对应的int值。

于是客户不爽了,他们想看到一个更有意义的字符,甚至字符串。 还好NH提供了两个类:EnumCharType和EnumStringType。

首先来看映射字符的情况,使用EnumCharType<T>还是比较容易的,直接来看NH的Test工程中的例子,entity和枚举定义如下

代码
    public class EnumCharBaz
    {
        
private Int32 id;
        
private SampleCharEnum type;

        
public virtual Int32 Id
        {
            
get { return id; }
            
set { id = value; }
        }

        
public virtual SampleCharEnum Type
        {
            
get { return type; }
            
set { type = value; }
        }
    }

    
public enum SampleCharEnum
    {
        On 
= 'N',
        Off 
= 'F',
        Dimmed 
= 'D'
    }

 

hbm则如下

代码
    <class name="EnumCharBaz" table="bc_ecfoobarbaz">
        
<id name="Id">
            
<generator class="assigned"/>
        
</id>
        
<property name="Type" column="type" type="NHibernate.Type.EnumCharType`1[[NHibernate.Test.TypesTest.SampleCharEnum, NHibernate.Test]], NHibernate"/>
    
</class>

 

让我们再一次的强烈谴责NH变态的泛型写法吧~~

再来看映射字符串,使用内建的EnumStringType<T>,也很轻松。依然来看NH中的Test例子

代码
    public class GenericEnumStringClass
    {
        public virtual int Id
        { 
            get;
            set;
        }

        public virtual SampleEnum EnumValue
        { 
            get;
            set;
        }
    }

    public enum SampleEnum
    {
        On,
        Off,
        Dimmed
    }

 

代码
    <class name="NHibernate.Test.TypesTest.GenericEnumStringClass, NHibernate.Test" table="bc_estr">
        
<id name="Id" column="id">
            
<generator class="assigned" />
        
</id>

        
<property name="EnumValue" type="NHibernate.Type.EnumStringType`1[[NHibernate.Test.TypesTest.SampleEnum, NHibernate.Test]], NHibernate" column="enumc"/>
    
</class>

 

结果上来说,NH是把你的枚举ToString之后存入了DB。

如果你想进一步定制枚举对应的String内容的话,可以继承EnumStringType。强烈不建议继承EnumStringType<T>,看看他的代码就知道他有多么废品

    [Serializable]
    
public class EnumStringType<T> : EnumStringType
    {
        
public EnumStringType() : base(typeof (T)) {}
    }

 

这不是啥有用的活儿都没做么。。。

为了使用上的方便,我实现了这样一个基类

代码
    public class GenericEnumStringType<TEnum> : EnumStringType where TEnum : struct
    {
        
protected static IDictionary<TEnum, string> Dictionary { getprivate set; }
        
static GenericEnumStringType()
        {
            
if (!typeof(TEnum).IsEnum)
            {
                
throw new ArgumentException("TEnum is not enum type"typeof(TEnum).FullName);
            }
            Dictionary 
= new Dictionary<TEnum, string>();
        }

        
public GenericEnumStringType()
            : 
base(typeof(TEnum))
        {
            
//do nothing
        }

        
public override object GetValue(object code)
        {
            
if (0 == Dictionary.Count)
            {
                
return base.GetValue(code);
            }
            var @enum 
= (TEnum)code;
            
if (Dictionary.ContainsKey(@enum))
            {
                
return Dictionary[@enum];
            }
            
throw new ArgumentException("Cannot convert", code.ToString());
        }

        
public override object GetInstance(object code)
        {
            
if (0 == Dictionary.Count)
            {
                
return base.GetInstance(code);
            }
            var str 
= code.ToString();
            
if (Dictionary.Values.Contains(str))
            {
                
return
                    Dictionary.Where(pair 
=> pair.Value.Equals(str, StringComparison.OrdinalIgnoreCase)).Select(
                        pair 
=> pair.Key).First();
            }
            
throw new ArgumentException("Cannot convert", str);
        }
    }

 

然后自定义枚举到字符串的类就简化成了这样

代码
    public class YNTypeStringType : GenericEnumStringType<YNType>
    {
        
static YNTypeStringType()
        {
            Dictionary.Add(YNType.Yes, 
"Yes!");
            Dictionary.Add(YNType.No, 
"No!");
        }
    }

 

hbm也映射这个类就好了,也不用写泛型了:)

好,今天就到这里~ 

posted @ 2010-08-27 18:21  jiaxingseng  阅读(1868)  评论(1编辑  收藏  举报