fluently - ¿Cómo mapea una enumeración como un valor int con NHibernate con fluidez?
nhibernate download c# (7)
Debes mantener los valores como int / tinyint en tu tabla DB. Para mapear su enumeración, debe especificar la asignación correctamente. Por favor, consulte el mapeo y la muestra enum a continuación,
Clase de mapeo
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, }
La pregunta lo dice todo, el valor predeterminado es mapear como una string
pero lo necesito para mapear como un int
.
Actualmente estoy usando PersistenceModel
para configurar mis convenciones si eso hace alguna diferencia. Gracias por adelantado.
Actualización Encontré que acceder a la última versión del código del tronco resolvió mis problemas.
Entonces, como mencioné, sacar la última versión de Fluent NHibernate del maletero me llevó a donde tenía que estar. Un mapeo de ejemplo para una enumeración con el último código es:
Map(quote => quote.Status).CustomTypeIs(typeof(QuoteStatus));
El tipo personalizado lo fuerza a manejarlo como una instancia de la enumeración en lugar de utilizar GenericEnumMapper<TEnum>
.
De hecho, estoy considerando enviar un parche para poder cambiar entre un mapeador enum que persista en una cadena y uno que persista en una int, ya que eso parece algo que debería poder configurar como una convención.
Esto apareció en mi actividad reciente y las cosas han cambiado en las versiones más nuevas de Fluent NHibernate para hacer esto más fácil.
Para hacer que todas las enumeraciones se mapeen 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 tu mapeo solo tiene que ser:
Map(quote => quote.Status);
Usted agrega la convención a su mapeo de Fluiber NHibernate como tal;
Fluently.Configure(nHibConfig)
.Mappings(mappingConfiguration =>
{
mappingConfiguration.FluentMappings
.ConventionDiscovery.AddFromAssemblyOf<EnumConvention>();
})
./* other configuration */
La forma de definir esta convención cambió a veces, ahora es:
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);
}
}
No te olvides de las enumeraciones que ExampleEnum? ExampleProperty
valores (como ExampleEnum? ExampleProperty
)! Necesitan ser chequeados 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);
}
}
Para aquellos que usan Fluiber NHibernate con Automapping (y potencialmente un contenedor IoC):
IUserTypeConvention
es la respuesta de @ Julien anterior: https://.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 Fluent NHibernate Automapping podría configurarse 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 CreateSessionFactory
se puede utilizar CreateSessionFactory
en un IoC como Castle Windsor (utilizando PersistenceFacility e instalador). *
Kernel.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod(() => CreateSessionFactory()),
Component.For<ISession>()
.UsingFactoryMethod(k => k.Resolve<ISessionFactory>().OpenSession())
.LifestylePerWebRequest()
);
Puede crear NHibernate IUserType
y especificarlo usando CustomTypeIs<T>()
en el mapa de propiedades.
así es como he mapeado una propiedad enum con un valor int:
Map(x => x.Status).CustomType(typeof(Int32));
¡funciona para mi!