88 votes

Comment mappez-vous une enum en tant que valeur int avec NHibernate?

La question dit vraiment tout, la valeur par défaut est de mapper en tant que string mais j'ai besoin de mapper en tant que int .

J'utilise actuellement PersistenceModel pour définir mes conventions si cela fait une différence. Merci d'avance.

Mise à jour Constaté que l'obtention de la dernière version du code à partir du coffre a résolu mes problèmes.

83voto

Julien Points 5966

La façon de définir cette convention a parfois changé il y a quelques temps:

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

45voto

Garry Shutler Points 20898

Donc, comme mentionné, l'obtention de la dernière version de NHibernate Fluent hors du tronc, m'a amené à l'endroit où je devais être. Un exemple de cartographie pour un enum avec la dernière version du code est:

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

Le type personnalisé forces qu'il soit géré comme une instance de l'enum plutôt que d'utiliser l' GenericEnumMapper<TEnum>.

En fait, je suis envisagent de soumettre un patch pour être en mesure de changer entre un enum mappeur qui persiste, une chaîne et un qui persiste int comme cela semble être quelque chose que vous devriez être en mesure de la définir comme une convention.


Cette surgi sur mon activité récente et les choses ont changé dans les versions plus récentes de Fluent NHibernate pour rendre cela plus facile.

Pour faire tous les énumérations être mappé comme des entiers, vous pouvez maintenant créer une convention comme suit:

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

Ensuite, votre cartographie ne doit être:

Map(quote => quote.Status);

Vous ajoutez de la convention de vos Couramment NHibernate cartographie comme;

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

40voto

SztupY Points 4586

N'oubliez pas les énumérations Nullables (comme ExampleEnum? ExampleProperty )! Ils doivent être vérifiés séparément. Voici comment procéder avec la nouvelle configuration de style 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);
    }
}
 

25voto

Felipe Points 199

Voici comment j'ai mappé une propriété enum avec une valeur int:

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

travaille pour moi!

1voto

lko Points 1062

Pour ceux qui utilisent Couramment NHibernate avec mappant automatiquement (et potentiellement un conteneur IoC):

L' IUserTypeConvention est que @Julien's réponse ci-dessus: http://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 fluidité de la NHibernate mappant automatiquement la configuration pourrait être configuré comme ceci:

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

*Ensuite, l' CreateSessionFactory peut être utilisé dans un Cio, tels que le Château de Windsor (à l'aide d'un PersistenceFacility et de l'installateur) facilement. *

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X