繁体   English   中英

映射到 Nhibernate 中的枚举位标志

[英]Mapping to an Enum bit flag in Nhibernate

采取以下枚举标志

[Flags]
enum Permssions
{
   CanComment = 1,
   CanEdit = 2,
   CanDelete = 4,
   CanRemoveUsers = 8,
   All = CanComment | CanEdit | CanDelete | CanRemoveUsers 
}

在 NHibernate 中,我在使用之前已映射到枚举:

<property type="n.Permssions, n.Permssions"
name="Permssions" column="Permssions"></property>

我的问题是,如何使用 NHibnerate 将位字段转换为标志字段?

当我 map 一个枚举,并且这个枚举有一个“int”类型的支持值时,我只是将我的枚举属性 map 到数据库中的一个 int 字段。 我没有遇到这方面的问题。
我也为标志枚举做过这个,这没有问题。 当您组合某些标志时,NHibernate 会将这些标志的“组合”保存到数据库中的指定列中。
当您检索具有“标志枚举”属性的实例时,NHibernate 会将其重构回正确的组合。
例如,如果 DB 包含“3”,则 NHibernate 将使用适当值的组合填充您的属性。
其实是让NHibernate自己搞定的:

<property name="OnCallType" column="OnCallType" />

其中 OnCallType 列在我的数据库中是 int 类型,而 OnCallType 属性是具有 flags 属性的枚举类型。

我认为最好的选择是使用自定义用户类型 您可以在其中 map 将 class 中的枚举添加到这两列。 这是一个使用 ICompositeUserMap 的示例,可用作指南:

尽管在您的情况下,仅实现 IUserType 就足够了。

这为我解决了这个问题:

在 class 映射中,我将其映射到具有枚举类型名称的自定义类型。

Map(x => x.MyEnumProperty).CustomType<EnumType>();

这并不能完全回答您的问题,但是在您的 class 和映射中使用 Int32 属性可能更容易,并使用 static class 来处理代码中的常量值,如下所示:

public static class Permissions
{
    public const int CanComment = 0x1;
    public const int CanEdit = 0x2;
    public const int CanDelete = 0x4;
    public const int CanRemoveUsers = 0x8;
    public const int All = CanComment | CanEdit | CanDelete | CanRemoveUsers;
}

我知道这并不理想,因为它不会将您的用户限制为固定的枚举值,并强制您处理代码中的原始整数,但我认为 Hibernate 会遇到按位枚举的问题。 它将尝试将 map 数据库中的一个值返回到特定的枚举值。 如果它在数据库中找到一个您没有明确枚举的值,它可能会窒息。 例如,如果它在数据库中找到“3”,它将无法将其 map 恢复为枚举值,除非您明确枚举每个组合,如 CanCommentAndEdit、CanCommentAndEditAndDelete 等。这可能违背了使用按位的目的枚举。

我将有一个用于 NHibernate 持久性的私有 int 字段和一个用于读取和写入 int 字段的标志枚举的公共 Getter/Setter 属性。 (NHibernate 可以配置为使用私有字段)

这样你就不必诉诸巫术魔法或混乱的常数来完成工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM