代码之家  ›  专栏  ›  技术社区  ›  Jaimal Chohan

fluent nhibernate映射枚举作为查找表

  •  19
  • Jaimal Chohan  · 技术社区  · 14 年前

    我有以下(简体)

    public enum Level
    {
        Bronze,
        Silver,
        Gold
    }
    
    public class Member
    {
        public virtual Level MembershipLevel { get; set; }
    }
    
    public class MemberMap : ClassMap<Member>
    {
        Map(x => x.MembershipLevel);
    }
    

    这将创建一个具有名为membershipplevel的列的表,该列的值为枚举字符串值。

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

    另外,我想不改变我的模型。

    2 回复  |  直到 14 年前
        1
  •  20
  •   Lachlan Roche    14 年前

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

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

    为了使枚举和查找表保持同步,我将向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() });
    }
    
        2
  •  5
  •   jweyrich    14 年前

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

    另一个原因是,如果更改枚举(在代码中),则必须将其与数据库表同步。因为枚举没有递增键(pk),所以它们不能如此简单地同步。假设从代码中删除一个枚举成员并重新编译它,会发生什么情况?如果你改变一个值呢?

    我希望我清楚地表明了我对这种做法的反对意见。因此,我强烈建议您存储枚举成员的名称或值。要按名称存储,请按如下方式映射:

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

    要存储这些值,请按照@lachlan在其答案中发布的操作。

    或者,如果您确实需要一个查找表,并且希望使用带有严格检查的枚举,请使用 PK (或为此使用值), 钥匙 价值 . 使用静态成员创建枚举,并使应用程序查询 姓名 价值观 当你开始的时候。如果事情不匹配,做任何你需要的。另外,这不能保证您的表在程序运行时不会更改,所以您最好确保它不会更改。