web-dev-qa-db-fra.com

Comment mappez-vous une énumération comme une valeur int avec NHibernate fluide?

La question en dit long, la valeur par défaut est qu'elle mappe en tant que string mais j'en ai besoin pour 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 J'ai trouvé que le fait d'accéder à la dernière version du code à partir du coffre a résolu mes problèmes.

87
Garry Shutler

La façon de définir cette convention a changé il y a quelque temps, c'est maintenant:

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

Donc, comme mentionné, le fait de sortir la dernière version de Fluent NHibernate du coffre m'a amené là où je devais être. Un exemple de mappage pour une énumération avec le dernier code est:

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

Le type personnalisé le force à être traité comme une instance de l'énumération plutôt qu'à l'aide de GenericEnumMapper<TEnum>.

J'envisage actuellement de soumettre un correctif pour pouvoir basculer entre un mappeur d'énumération qui persiste une chaîne et celui qui persiste un int car cela semble être quelque chose que vous devriez pouvoir définir en tant que convention.


Cela est apparu sur mon activité récente et les choses ont changé dans les nouvelles versions de Fluent NHibernate pour rendre cela plus facile.

Pour que toutes les énumérations soient mappées sous forme d'entiers, vous pouvez maintenant créer une convention comme ceci:

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

Votre cartographie doit alors être:

Map(quote => quote.Status);

Vous ajoutez la convention à votre mappage Fluent NHibernate comme ceci;

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

N'oubliez pas les énumérations nullables (comme ExampleEnum? ExampleProperty)! Ils doivent être vérifiés séparément. Voici comment cela se fait 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);
    }
}
40
SztupY

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

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

travaille pour moi!

25
Felipe

Pour ceux qui utilisent Fluent NHibernate avec Automapping (et potentiellement un conteneur IoC):

Le IUserTypeConvention est comme @ la réponse de Julien ci-dessus: 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 configuration Fluent NHibernate Automapping peut être configurée comme suit:

    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, le CreateSessionFactory peut être utilisé facilement dans un IoC tel que Castle Windsor (en utilisant un PersistenceFacility et un installateur). *

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

Vous devez conserver les valeurs int/tinyint dans votre table DB. Pour mapper votre énumération, vous devez spécifier le mappage correctement. Veuillez voir ci-dessous la cartographie et l'énumération de l'échantillon,

Classe de mappage

 public class TransactionMap: ClassMap Transaction 
 {
 public TransactionMap () 
 {
 // Autres mappages 
 .... . 
 // Mappage pour l'énumération 
 Carte (x => x.Status, "Status"). CustomType (); 
 
 Table ("Transaction") ; 
} 
} 

Enum

 public enum TransactionStatus 
 {
 En attente = 1, 
 Traité = 2, 
 RolledBack = 3, 
 Bloqué = 4, 
 Remboursé = 5, 
 Déjà traité = 6, 
}
0
Arkadas Kilic

Vous pouvez créer un NHibernate IUserType et le spécifier à l'aide de CustomTypeIs<T>() sur la carte de propriétés.

0
James Gregory