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

时间:2009-01-13 13:50:44

标签: nhibernate fluent-nhibernate

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

我目前正在使用PersistenceModel来设置我的约定,如果这有任何区别的话。提前谢谢。

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

7 个答案:

答案 0 :(得分:83)

定义此约定的方法有时会改变,现在是:

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);
    }
}

答案 1 :(得分: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 */

答案 2 :(得分: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);
    }
}

答案 3 :(得分:25)

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

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

适合我!

答案 4 :(得分:1)

对于那些使用Fluent NHibernate和Automapping(以及可能是IoC容器)的人:

IUserTypeConvention与@ Julien 的答案相同: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可以轻松地在诸如Castle Windsor之类的IoC中使用(使用PersistenceFacility和安装程序)。 *

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

答案 5 :(得分:0)

您可以创建一个NHibernate IUserType,并在属性地图上使用CustomTypeIs<T>()指定它。

答案 6 :(得分:0)

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

映射类

public class TransactionMap : ClassMap Transaction
{
    public TransactionMap()
    {
        //Other mappings
        .....
        //Mapping for enum
        Map(x => x.Status, "Status").CustomType();

        Table("Transaction");
    }
}

<强>枚举

public enum TransactionStatus
{
   Waiting = 1,
   Processed = 2,
   RolledBack = 3,
   Blocked = 4,
   Refunded = 5,
   AlreadyProcessed = 6,
}