我正在尝试将模型中的枚举属性(System.DayOfWeek的实例)映射到整数数据库字段。 模型中的其他枚举属性应该映射到字符串,所以我不希望定义约定。
我知道这应该可以使用流畅的映射,如:
Map(x => x.DayOfWeek).CustomType<int>();
事实上,乍一看这似乎有效。
但是,我注意到每次刷新会话时都会更新具有以这种方式映射的属性的实体实例,即使没有对它们进行任何修改。
为了找出导致此刷新的原因,我设置了一个IPreUpdateEventListener,并检查了实体的OldState和State。 请参见附图。在OldState中,相关对象是int,而在State中它是DayOfWeek。
如果我使用未指定type属性的HBM XML映射,则不会出现此问题。
因此...
这是GenericEnumMapper中的错误还是缺点? 有没有办法告诉FNH映射不要在生成的HBM上指定任何类型属性? 如果没有,我可以指定NH用于枚举的默认类型(以及它是什么)?
答案 0 :(得分:23)
如果您使用我的枚举惯例,那么您就没有这个问题。
public class EnumConvention : IPropertyConvention, IPropertyConventionAcceptance
{
public void Apply(IPropertyInstance instance)
{
instance.CustomType(instance.Property.PropertyType);
}
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
{
criteria.Expect(x => x.Property.PropertyType == typeof(AddressType) ||
x.Property.PropertyType == typeof(Status) ||
x.Property.PropertyType == typeof(DayOfWeek));
}
}
然后,您可以像往常一样映射您的媒体资源:
Map(x => x.DayOfWeek);
编辑:更新了约定,以选择用于int转换的特定枚举。未在此处检查的所有枚举将映射为字符串。您可能需要对实际测试的内容进行一些实验。我不确定属性类型是否会直接执行。
答案 1 :(得分:5)
我知道我迟到了 - 这个问题已经过去两年了。但是既然我偶然发现了这个问题,我可能会为我解决这个问题:
Map(x => x.DayOfWeek).CustomType<enumType>();
它为我做了诀窍:它每次都停止更新。
答案 2 :(得分:4)
我使用的一个解决方法是拥有一个int支持字段,并让NHibernate使用它进行映射。
每当NHibernate必须进行强制转换以将新值与旧值进行比较时 - 它总是标记为脏 - 导致刷新。
答案 3 :(得分:1)
对我有用的简单方法是将地图的自定义类型从int
更改为PersistentEnumType
。确保声明一个通用版本,以使您的生活更轻松:
public class PersistentEnumType<T> : PersistentEnumType {
public PersistentEnumType() : base(typeof(T)) {}
}
然后使用
Map(x => x.DayOfWeek)
.CustomType<PersistentEnumType<System.DayOfWeek>>();
这不需要更改您的实体,只需要映射,并且可以基于每个属性进行更改。
查看更多here。
答案 4 :(得分:0)
这取决于你是否需要特别将DayOfWeek作为整数。
如果您正在作为映射的一部分进行投射,则相等将始终失败,并且该属性将被标记为脏。
我可能会映射:
地图(x =&gt; x.DayOfWeek).CustomType();
并创建一个只读属性,如果确实需要,则将DayOfWeek值显示为整数。无论如何,映射作为实际类型应该起作用并防止虚假。
答案 5 :(得分:0)
你可能会考虑另一种方法;我发现Fabio Maulo well known instance types的使用对于这些用途来说非常宝贵。当您发现自己试图扩展基本枚举可以做的事情时(例如,提供本地化描述等),这些好处立即显而易见。