使用流利的 nhibernate 映射枚举
Posted
技术标签:
【中文标题】使用流利的 nhibernate 映射枚举【英文标题】:Mapping enum with fluent nhibernate 【发布时间】:2010-12-01 18:25:32 【问题描述】:我正在按照http://wiki.fluentnhibernate.org/Getting_started 教程使用 Fluent NHibernate 创建我的第一个 NHibernate 项目
我有两张桌子
1) 带有字段的帐户
Id
AccountHolderName
AccountTypeId
2) 带字段的 AccountType
Id
AccountTypeName
目前账户类型可以是储蓄或活期 所以表 AccountTypes 存储 2 行 1 - 储蓄 2 - 当前
对于AccoutType 表我已经定义了枚举
public enum AccountType
Savings=1,
Current=2
对于 Account 表,我定义了实体类
public class Account
public virtual int Id get; private set;
public virtual string AccountHolderName get; set;
public virtual string AccountType get; set;
流畅的nhibernate映射是:
public AgencyMap()
Id(o => o.Id);
Map(o => o.AccountHolderName);
Map(o => o.AccountType);
当我尝试运行解决方案时,它给出了一个异常 - InnerException = "(XmlDocument)(2,4): XML validation error: The element 'class' in namespace 'urn:nhibernate-mapping-2.2' has内容不完整。预期的可能元素列表:命名空间“ur...”中的“元、子选择、缓存、同步、注释、元组、id、复合 ID”。
我猜这是因为我没有为 AccountType 指定任何映射。
问题是:
-
如何使用 AccountType 枚举
而不是 AccountType 类?
也许我走错了路。有没有更好的方法来做到这一点?
谢谢!
【问题讨论】:
【参考方案1】:以下显然不再有效https://***.com/a/503327/189412
这样做怎么样:
public AgencyMap()
Id(o => o.Id);
Map(o => o.AccountHolderName);
Map(o => o.AccountType).CustomType<AccountType>();
自定义类型处理一切:)
【讨论】:
啊哈!我正在使用 CustomSqlType 但它不起作用!我需要的是 CustomType! AcountType 是一个枚举,因此所有实体在加载后都会变脏。见***.com/questions/3531937/… 这似乎是正确的,但会生成“幻影”更新。正确的映射是:CustomType。否则,就像 schoetbi 所说,实体在加载后是脏的。来源:groups.google.com/forum/#!searchin/fluent-nhibernate/enum/… 这不再有效!您需要在更新版本的 FNH 中使用 .CustomTypepublic class Account
public virtual int Id get; private set;
public virtual string AccountHolderName get; set;
public virtual AccountType AccountType get; set;
public AgencyMap()
Id(o => o.Id);
Map(o => o.AccountHolderName);
Map(o => o.AccountType);
Fluent NHibernate 默认将枚举值保存为字符串,如果你想覆盖你需要为其提供约定。比如:
public class EnumConvention :
IPropertyConvention,
IPropertyConventionAcceptance
#region IPropertyConvention Members
public void Apply(IPropertyInstance instance)
instance.CustomType(instance.Property.PropertyType);
#endregion
#region IPropertyConventionAcceptance Members
public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
criteria.Expect(x => x.Property.PropertyType.IsEnum ||
(x.Property.PropertyType.IsGenericType &&
x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
);
#endregion
几乎忘记了您还需要将约定添加到流利的配置中。您在添加映射的同一位置执行此操作:
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<BillingRecordMap>()
.Conventions.AddFromAssemblyOf<EnumConvention>()
【讨论】:
查看这篇文章/评论,了解如何扩展它以支持可为空的枚举:***.com/questions/439003/… 我用你的建议 Mustafa 更新了代码。非常感谢!【参考方案3】:实现这一点的好方法是实现接口 IUserType 并创建一个具有写入和读取规则的 CustomType,这是一个布尔示例:
public class CharToBoolean : IUserType
public SqlType[] SqlTypes => new[] NHibernateUtil.String.SqlType ;
public Type ReturnedType => typeof(bool);
public bool IsMutable =>true;
public object Assemble(object cached, object owner)
return (cached);
public object DeepCopy(object value)
return (value);
public object Disassemble(object value)
return (value);
public new bool Equals(object x, object y)
if (ReferenceEquals(x, y)) return true;
var firstObject = x as string;
var secondObject = y as string;
if (string.IsNullOrEmpty(firstObject) || string.IsNullOrEmpty(secondObject)) return false;
if (firstObject == secondObject) return true;
return false;
public int GetHashCode(object x)
return ((x != null) ? x.GetHashCode() : 0);
public object NullSafeGet(IDataReader rs, string[] names, object owner)
var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]);
if (obj == null) return null;
var value = (string)obj;
return value.ToBoolean();
public void NullSafeSet(IDbCommand cmd, object value, int index)
if(value != null)
if ((bool)value)
((IDataParameter)cmd.Parameters[index]).Value = "S";
else
((IDataParameter)cmd.Parameters[index]).Value = "N";
else
((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
public object Replace(object original, object target, object owner)
return original;
映射:
this.Map(x => x.DominioGenerico).Column("fldominiogen").CustomType<CharToBoolean>();
这是一个示例,但您可以使用其他类型进行此操作。
【讨论】:
以上是关于使用流利的 nhibernate 映射枚举的主要内容,如果未能解决你的问题,请参考以下文章