在Nhibernate中使用枚举
时间:2010-08-27 来源:jiaxingseng
我们会经常有这种需求:把一个字段映射成一个枚举。
于是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 { get; private 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也映射这个类就好了,也不用写泛型了:)
好,今天就到这里~
相关阅读 更多 +