我有一个类,它有一个enum类型,指示消息类型是Email还是Sms。定义了enum类型:
public enum ReminderType
{
Email = 1,
Sms = 2
}
使用此类型的类如下:
public class Reminder : EntityBase
{
public virtual string Origin { get; set; }
public virtual string Recipient { get; set; }
public virtual ReminderType Type { get; set; }
public virtual Business Business { get; set; }
public virtual DateTime Created { get; set; }
public Reminder()
{
Created = DateTime.UtcNow;
}
}
当我尝试将一个类型为提醒的实体持久化到数据库中时,我得到了以下错误:
System.Data.SqlClient.SqlException (0x80131904): Conversion failed when converting the nvarchar value 'Email' to data type int.
支持字段的类型是int
,所以我不确定为什么NHibernate试图默认映射字符串表示。我使用的是Fluent NHibernate,相关的映射代码是:
mappings.Override<Reminder>(map =>
{
map.Map(x => x.Type).Column("Type")
});
我很确定NHibernate的默认行为是将enum映射为int,那么为什么在这种情况下它不这样做呢?我正在使用SQL Server 2005,如果这很重要。
我正在做同样的事情,让它像这样工作…
在我的例子中,EmployeeType是enum类
Map(x => x.EmployeeType, "EmployeeType_Id").CustomType(typeof (EmployeeType));
我不知道为什么这个人一直发帖然后删除他们的评论或回答,但是他们提供的链接()确实回答了我的问题。我选择不对约定使用完整的类定义,而是在映射代码中使用内联约定,如下:
var mappings = AutoMap.AssemblyOf<Business>()
.Where(x => x.IsSubclassOf(typeof(EntityBase)))
.IgnoreBase(typeof(EntityBase))
.Conventions.Add
(
ConventionBuilder.Id.Always(x => x.GeneratedBy.Identity()),
ConventionBuilder.HasMany.Always(x => x.Cascade.All()),
ConventionBuilder.Property.Always(x => x.Column(x.Property.Name)),
Table.Is(o => Inflector.Pluralize(o.EntityType.Name)),
PrimaryKey.Name.Is(o => "Id"),
ForeignKey.EndsWith("Id"),
DefaultLazy.Always(),
DefaultCascade.All(),
ConventionBuilder.Property.When(
c => c.Expect(x => x.Property.PropertyType.IsEnum),
x => x.CustomType(x.Property.PropertyType))
);
最后一个约定构建器语句达到了目的。我很好奇为什么现在Fluent NHibernate的默认值是将枚举映射为字符串。这似乎没有多大意义。
你不应该在NHibernate中将Enum映射为int。这就成了幽灵更新的一个原因。
最好的方法就是在XML映射中不设置type属性。为了在Fluent NHibernate中实现这一点,你可以使用.CustomType(string.Empty)
。
你可以在这里找到一些额外的信息。