在 NHibernate 中映射枚举集合

发布于 2024-09-24 23:43:51 字数 1069 浏览 0 评论 0原文

我试图使用 Fluent NHibernate 映射 NHibernate 中的枚举集合,然后对该枚举集合的内容执行查询,但系统每次都会抛出异常。

我有一个 Widget 类,映射到 Widget 表。还有一个 WidgetType 枚举,Widget 的单个实例可以有许多 WidgetType,通过 WidgetTypes 属性进行映射。该属性需要映射到一个单独的表 WidgetTypeRef,其中包含两个整数列:WidgetId 和 WidgetType。

public class Widget
{
  /* omitted */
  public IList<WidgetType> WidgetTypes { get; set; }
}
public enum WidgetType
{
  SomeType = 0,
  SomeOtherType = 1,
  YetOneMoreType = 2
}
public partial class WidgetMapping : IAutoMappingOverride<Widget>
{
  public void Override(AutoMapping<Widget> mapping)
  {
    /* omitted */
    mapping.HasMany(w => w.WidgetTypes)
      .Table("WidgetTypeRef")
      .KeyColumn("WidgetId")
      .Element("WidgetType");
  }
}

我无法控制数据库模式;架构无法更改。该架构必须存储与 Widget 关联的 WidgetType 的整数值,并且无法转换以匹配枚举的字符串版本。我非常努力保持枚举的强类型,并避免为 Ref 表创建新实体。

其他类具有与“.CustomType(typeof(someTypeEnum)”配置配合使用的基于枚举的类型属性,但 HasMany 映射上没有 CustomType 属性。使用上面的 HasMany 映射,对集合的查询会抛出“无法确定成员类型”异常。

这可能吗?应该如何设置属性?应该如何配置 Fluent 映射?如何查询集合(我的查询只需要相当于 Any 或 Contains)?

I'm trying to map a collection of enums in NHibernate using Fluent NHibernate, and then perform queries against the contents of that enum collection, but the system throws exceptions every time.

I have a Widget class, mapped to the Widget table. There is also a WidgetType enum, and a single instance of Widget can have many WidgetTypes, mapped through the WidgetTypes property. The property needs to be mapped to a separate table, WidgetTypeRef, with two integer columns: WidgetId and WidgetType.

public class Widget
{
  /* omitted */
  public IList<WidgetType> WidgetTypes { get; set; }
}
public enum WidgetType
{
  SomeType = 0,
  SomeOtherType = 1,
  YetOneMoreType = 2
}
public partial class WidgetMapping : IAutoMappingOverride<Widget>
{
  public void Override(AutoMapping<Widget> mapping)
  {
    /* omitted */
    mapping.HasMany(w => w.WidgetTypes)
      .Table("WidgetTypeRef")
      .KeyColumn("WidgetId")
      .Element("WidgetType");
  }
}

I have no control over the DB schema; the schema cannot be changed. The schema must store the integer values of the WidgetTypes associated with the Widget, and cannot be converted to match the string version of the enum. I'm very much trying to keep the strong typing of the enum, and am avoiding creating a new entity for the Ref table.

Other classes have enum-based type properties that work with the ".CustomType(typeof(someTypeEnum)" configuration, but there is no CustomType property on a HasMany mapping. Using this HasMany mapping above, queries into the collection throw a "Could not determine member type" exception.

Is this even possible? How should the property be set up? How should the Fluent mapping be configured? How do I query in to the collection (my query only needs the equivalent of an Any or Contains)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

秋意浓 2024-10-01 23:43:51
public class EnumToIntConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

使用该约定,具有以下枚举:

public enum Status
{
    Inactive = 0,
    Active = 1,
    Canceled = 2
}

并像这样设置它(也应该与 Fluent 映射一起使用):

var cfg = Fluently.Configure()
    .Database(configurer)
    .Mappings(m =>
    {
        m.AutoMappings.Add(AutoMap.Assemblies(Assembly.GetExecutingAssembly())
            .Where(type => AutomapAssemblies.Contains(type.Namespace))
            .Conventions.Add<EnumToIntConvention>()  // Magic code goes here!
            .Conventions.Add());
    });

将保存 integer 值而不是 string 值。

public class EnumToIntConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum);
    }

    public void Apply(IPropertyInstance target)
    {
        target.CustomType(target.Property.PropertyType);
    }
}

Using that convention, having the following Enum:

public enum Status
{
    Inactive = 0,
    Active = 1,
    Canceled = 2
}

And setting it up like this (should work with Fluent mappings too):

var cfg = Fluently.Configure()
    .Database(configurer)
    .Mappings(m =>
    {
        m.AutoMappings.Add(AutoMap.Assemblies(Assembly.GetExecutingAssembly())
            .Where(type => AutomapAssemblies.Contains(type.Namespace))
            .Conventions.Add<EnumToIntConvention>()  // Magic code goes here!
            .Conventions.Add());
    });

Will save the integer value instead of the string value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文