如何使用流利的NHibernate将枚举映射为int值?


88

问题确实说明了一切,默认值是将其映射为,string但我需要将其映射为int

我目前正在使用它PersistenceModel来设置我的约定,如果有什么不同的话。提前致谢。

更新 发现从主干获取最新版本的代码解决了我的麻烦。


5
如果您自己解决了问题,则应该回答,然后将其标记为正确的答案,以便将来的搜索者找到。
杰夫·马丁

你能发布答案吗?
mxmissile

做的家伙。抱歉耽搁了。我真的不确定应该如何处理这个问题,因为我只是需要最新版本的库,而这个问题更多的是非问题。
加里·舒特勒

2
Google机器人的食物:在为枚举映射实现此功能之前,我获得了“非法访问加载集合”的权限。
4imble 2010年

Answers:


84

定义此约定的方式有时是在以前更改的,现在是:

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

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

4
这是最新版本的流利的nhibernate的正确答案
Sean Chambers 2009年

磕碰。^^肖恩说了什么。
Martin Suchanek 2010年

1
看起来对于所有枚举类型都可以正常工作,但是如果您想将某些作为字符串而将某些作为整数怎么办?我认为这应该可以在属性映射级别进行配置。
2010年

4
请参见下面@SztupY的答案,该答案将其扩展为允许可为空的枚举。stackoverflow.com/questions/439003/…–
乔恩·亚当斯

45

因此,如上所述,从后备箱中获取最新版本的Fluent NHibernate使我到达了需要的位置。具有最新代码的枚举的映射示例为:

Map(quote => quote.Status).CustomTypeIs(typeof(QuoteStatus));

自定义类型强制将其作为枚举的实例进行处理,而不是使用GenericEnumMapper<TEnum>

我实际上正在考虑提交一个修补程序,以便能够在保留字符串的枚举映射器和保留int的枚举映射器之间进行更改,因为这似乎应该可以设置为约定。


这突然出现在我最近的活动中,而Fluent NHibernate的较新版本中的内容进行了更改,从而使此操作变得更加容易。

为了使所有枚举都映射为整数,您现在可以创建如下约定:

public class EnumConvention : IUserTypeConvention
{
    public bool Accept(IProperty target)
    {
        return target.PropertyType.IsEnum;
    }

    public void Apply(IProperty target)
    {
        target.CustomTypeIs(target.PropertyType);
    }

    public bool Accept(Type type)
    {
        return type.IsEnum;
    }
}

然后,您的映射只需是:

Map(quote => quote.Status);

像这样将约定添加到Fluent NHibernate映射中;

Fluently.Configure(nHibConfig)
    .Mappings(mappingConfiguration =>
    {
        mappingConfiguration.FluentMappings
            .ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
    })
    ./* other configuration */

3
默认为“ int模式”。谁坚持枚举为字符串?
安德鲁·布洛克(

4
可能是已有字符串值的旧式数据库
克里斯·海恩斯

4
+1疯狂。// @安德鲁·布洛克(Andrew Bullock):回答您的问题:处理现实世界数据库的任何人。
Sky Sanders

FN中是否有任何IProperty接口?
Tien Do

40

不要忘记可为空的枚举(如ExampleEnum? ExampleProperty)!它们需要单独检查。这是通过新的FNH样式配置完成的:

public class EnumConvention : IUserTypeConvention
{
    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
    {
        criteria.Expect(x => x.Property.PropertyType.IsEnum ||
            (x.Property.PropertyType.IsGenericType && 
             x.Property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>) &&
             x.Property.PropertyType.GetGenericArguments()[0].IsEnum)
            );
    }

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

4
+1为这个加法!第一个版本不适用于可为空的枚举(它们保留为字符串)。
龙大

@SztupY数据库中的列类型是int?当类型接受Flags时?像:MyEnum.Active | MyEnum.Paused
ridermansb

@RidermandeSousaBarbosa:对于标志点击这里:stackoverflow.com/questions/2805661/...
SztupY

25

这就是我用int值映射枚举属性的方式:

Map(x => x.Status).CustomType(typeof(Int32));

为我工作!


2
感谢您提供最简单的答案
Mike

我对此唯一的担心是,您必须记住将其应用于每个枚举。这就是约定的创建目的。
加里·舒特勒

这可以读取,但是在尝试条件查询时失败。在我尝试过的所有情况下,建立一个约定(请参阅此问题的答案)都可以。
Thomas Bratt 2010年

好吧,我认为这很棒-但这会引起问题:请参阅这篇文章。nhforge.org/blogs/nhibernate/archive/2008/10/20/...
UpTheCreek

@UpTheCreek似乎已解决,现在由NH团队的James Gregory建议:mail-archive.com/fluent-nhibernate@googlegroups.com/…–
Ilya Kogan

1

对于那些将Fluent NHibernate与Automapping一起使用的人(可能还有一个IoC容器):

IUserTypeConvention是@ 朱利安上面的答案:https : //stackoverflow.com/a/1706462/878612

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

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

Fluent NHibernate Automapping配置可以这样配置:

    protected virtual ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(SetupDatabase)
            .Mappings(mappingConfiguration =>
                {
                    mappingConfiguration.AutoMappings
                        .Add(CreateAutomappings);
                }
            ).BuildSessionFactory();
    }

    protected virtual IPersistenceConfigurer SetupDatabase()
    {
        return MsSqlConfiguration.MsSql2008.UseOuterJoin()
        .ConnectionString(x => 
             x.FromConnectionStringWithKey("AppDatabase")) // In Web.config
        .ShowSql();
    }

    protected static AutoPersistenceModel CreateAutomappings()
    {
        return AutoMap.AssemblyOf<ClassInAnAssemblyToBeMapped>(
            new EntityAutomapConfiguration())
            .Conventions.Setup(c =>
                {
                    // Other IUserTypeConvention classes here
                    c.Add<EnumConvention>();
                });
    }

*然后CreateSessionFactory可以轻松地在IoC中使用,例如Castle Windsor(使用PersistenceFacility和安装程序)。*

    Kernel.Register(
        Component.For<ISessionFactory>()
            .UsingFactoryMethod(() => CreateSessionFactory()),
            Component.For<ISession>()
            .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
            .LifestylePerWebRequest() 
    );


0

您应该在数据库表中将值保留为int / tinyint。为了映射您的枚举,您需要正确指定映射。请参见下面的映射和枚举示例,

映射类

公共类TransactionMap:ClassMap事务
{
    公共TransactionMap()
    {
        //其他映射
        .....
        //映射为枚举
        Map(x => x.Status,“ Status”)。CustomType();

        Table(“ Transaction”);
    }
}

枚举

公共枚举TransactionStatus
{
   等待= 1,
   已处理= 2
   RolledBack = 3,
   封锁= 4,
   退款= 5
   已处理= 6,
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.