¿Cómo mapear un enum como un valor int con fluent NHibernate?


La pregunta lo dice todo realmente, el valor predeterminado es que se mapee como string pero lo necesito para mapear como int.

Actualmente estoy usando PersistenceModel para establecer mis convenciones si eso hace alguna diferencia. Gracias de antemano.

Actualización Encontré que entrar en la última versión del código desde el tronco resolvió mis problemas.

Author: Garry Shutler, 2009-01-13

7 answers

La forma de definir esta convención cambió a veces hace, es ahora:

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);
    }
}
 82
Author: Julien,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-10 08:48:26

Así que, como se mencionó, sacar la última versión de Fluent NHibernate del maletero me llevó a donde necesitaba estar. Un ejemplo de asignación para una enumeración con el código más reciente es:

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

El tipo personalizado obliga a manejarlo como una instancia de la enumeración en lugar de usar el GenericEnumMapper<TEnum>.

En realidad estoy considerando enviar un parche para poder cambiar entre un mapeador de enum que persiste una cadena y uno que persiste una int, ya que parece algo que debería ser capaz de establecer como un convención.


Esto apareció en mi actividad reciente y las cosas han cambiado en las versiones más recientes de Fluent NHibernate para hacer esto más fácil.

Para hacer que todas las enumeraciones se asignen como enteros, ahora puede crear una convención como esta:

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

Entonces su mapeo solo tiene que ser:

Map(quote => quote.Status);

Se agrega la convención a su asignación Fluida de NHibernate de la siguiente manera;

Fluently.Configure(nHibConfig)
    .Mappings(mappingConfiguration =>
    {
        mappingConfiguration.FluentMappings
            .ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
    })
    ./* other configuration */
 45
Author: Garry Shutler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-26 07:37:52

¡No te olvides de las enumeraciones nullables (como ExampleEnum? ExampleProperty)! Deben ser comprobados por separado. Así es como se hace con la nueva configuración de estilo 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);
    }
}
 40
Author: SztupY,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-11 19:33:17

Así es como he mapeado una propiedad enum con un valor int:

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

Funciona para mí!

 25
Author: Felipe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-29 10:42:13

Para aquellos que usan Fluent NHibernate con Automapping (y potencialmente un contenedor IoC):

El IUserTypeConvention es como @Julien's respuesta anterior: 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);
    }
}

La configuración de Automapping de Fluent NHibernate se puede configurar así:

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

*Entonces el CreateSessionFactory puede ser utilizado en un CoI como Castle Windsor (usando un PersistenceFacility e instalador) fácilmente. *

    Kernel.Register(
        Component.For<ISessionFactory>()
            .UsingFactoryMethod(() => CreateSessionFactory()),
            Component.For<ISession>()
            .UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
            .LifestylePerWebRequest() 
    );
 1
Author: lko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:33:01

Puede crear un NHibernate IUserType y especificarlo usando CustomTypeIs<T>() en el mapa de propiedades.

 0
Author: James Gregory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-01-13 15:57:52

Debe mantener los valores como int / tinyint en su tabla DB. Para asignar su enumeración debe especificar la asignación correctamente. Por favor vea abajo mapeo y muestra de enum,

Clase de asignación

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

        Table("Transaction");
    }
}

Enum

public enum TransactionStatus
{
   Waiting = 1,
   Processed = 2,
   RolledBack = 3,
   Blocked = 4,
   Refunded = 5,
   AlreadyProcessed = 6,
}
 0
Author: Arkadas Kilic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-24 15:41:36