流畅的NHibernate Map Enum作为查找表

时间:2010-04-02 20:02:42

标签: nhibernate fluent-nhibernate

我有以下(简化)

public enum Level
{
    Bronze,
    Silver,
    Gold
}

public class Member
{
    public virtual Level MembershipLevel { get; set; }
}

public class MemberMap : ClassMap<Member>
{
    Map(x => x.MembershipLevel);
}

这将创建一个包含名为MembershipLevel的列的表,其值为Enum字符串值。

我想要的是将整个枚举创建为查找表,其中成员表以整数值作为FK引用它。

另外,我想在不改变模型的情况下这样做。

2 个答案:

答案 0 :(得分:20)

要将枚举属性映射为int列,请使用方法CustomType

public class MemberMap : ClassMap<Member>
{
    Map( x => x.MembershipLevel ).CustomType<int>();
}

为了使enum和lookup表保持同步,我会将查找表和数据添加到sql脚本中。集成测试可以验证枚举和查找表值是否相同。

如果您希望SchemaExport创建此表,请为其添加类和映射。

public class MembershipLevel
{
    public virtual int Id { get; set; }
    public virtual string Code { get; set; }
}

public class MembershipLevelMap : ClassMap<MembershipLevel>
{
    Id( x => x.Id );
    Map( x => x.Code );
}

如果要使用SchemaExport创建表,则还需要填充它:

foreach (Level l in Enum.GetValues( typeof( Level ))) {
    session.Save( new MembershipLevel{ Id = (int) l, Code = l.ToString() });
}

答案 1 :(得分:5)

我不这样做,因为你的Enum声明不是动态的,或者更简单,它不会在不重新编译的情况下改变,而你的查找表可能随时改变。如果枚举和查找表的值不匹配,那么下一步是什么?

另一个原因是如果更改枚举(在代码中),则必须将其与数据库表同步。由于Enums没有增量密钥(PK),因此它们无法如此简单地同步。假设您从代码中删除一个Enum成员并重新编译它,应该发生什么?如果你改变一个值?

我希望我明确反对这种方法。所以我强烈建议存储枚举成员的名称或值。要按名称存储它,只需这样映射:

public class MemberMap : ClassMap<Member>
{
    Map(x => x.MembershipLevel, "level")
        .CustomType<GenericEnumMapper<Level>>()
        .Not.Nullable();
}

要存储这些值,请按@Lachlan的答案发布。

或者,如果您确实需要查找表并希望使用带有严格检查的枚举,请使用 PK 创建一个普通模型(或使用此值), KEY VALUE 。使用静态成员创建枚举,并在启动时让应用程序在数据库中查询名称。如果事情不匹配,做任何你需要的事情。此外,这并不能保证您的程序在程序运行时不会更改,所以最好不要确保它不会。