2011-04-11 8 views
6

Tengo una clase que tiene un tipo de enumeración que indica si el tipo de mensaje es Correo electrónico o SMS. El tipo de enumeración se define:NHibernate, SQL Server - mapping de enumeración a int

public enum ReminderType 
{ 
    Email = 1, 
    Sms = 2 
} 

La clase que utiliza este tipo se parece a:

public class Reminder : EntityBase 
{ 
    public virtual string Origin { get; set; } 
    public virtual string Recipient { get; set; } 
    public virtual ReminderType Type { get; set; } 
    public virtual Business Business { get; set; } 
    public virtual DateTime Created { get; set; } 

    public Reminder() 
    { 
     Created = DateTime.UtcNow; 
    } 
} 

Cuando trato de persistir una entidad de tipo recordatorio a la base de datos, sin embargo, me sale el siguiente error:

System.Data.SqlClient.SqlException (0x80131904): Conversion failed when converting the nvarchar value 'Email' to data type int. 

el campo respaldo es de tipo int, así que no estoy seguro de por qué NHibernate está tratando de trazar la representación de cadena por defecto. Estoy usando Fluido NHibernate, y el código de asignación relevante es:

mappings.Override<Reminder>(map => 
{ 
    map.Map(x => x.Type).Column("Type") 
}); 

Estoy bastante seguro el comportamiento predeterminado de NHibernate es mapear las enumeraciones como enteros, ¿por qué es no hacerlo en este caso? Estoy usando SQL Server 2005, si eso importa.

+0

El correo electrónico es el valor de cadena de la propiedad Tipo. Nhibernate debería tratar de almacenarlo como el valor entero 1, pero está tratando de almacenar la cadena 'Correo electrónico' en su lugar, de ahí el error. No estoy seguro de por qué está haciendo eso ... – Chris

+0

http://stackoverflow.com/questions/439003/how-do-you-map-an-enum-as-an-int-value-with-fluent- nhibernate – dotjoe

+0

o http://stackoverflow.com/questions/1483044/mapping-enum-with-fluent-nhibernate –

Respuesta

3

No sé por qué esta persona mantiene publicar y luego borrando su comentario o respuesta, pero el enlace que proporcionaron() responde mi pregunta. Yo he optado por no ir con una definición de clase golpe completo para la convención, sino más bien, una convención en línea en el código asignaciones, así:

var mappings = AutoMap.AssemblyOf<Business>() 
    .Where(x => x.IsSubclassOf(typeof(EntityBase))) 
    .IgnoreBase(typeof(EntityBase)) 
    .Conventions.Add 
    (
     ConventionBuilder.Id.Always(x => x.GeneratedBy.Identity()), 
     ConventionBuilder.HasMany.Always(x => x.Cascade.All()), 
     ConventionBuilder.Property.Always(x => x.Column(x.Property.Name)), 
     Table.Is(o => Inflector.Pluralize(o.EntityType.Name)), 
     PrimaryKey.Name.Is(o => "Id"), 
     ForeignKey.EndsWith("Id"), 
     DefaultLazy.Always(), 
     DefaultCascade.All(), 

     ConventionBuilder.Property.When(
      c => c.Expect(x => x.Property.PropertyType.IsEnum), 
      x => x.CustomType(x.Property.PropertyType)) 
    ); 

La última declaración del constructor convención hizo el truco. Tengo curiosidad por saber por qué el valor predeterminado de Fluent NHibernate es mapear enumeraciones como cadenas ahora. Eso no parece tener mucho sentido.

+1

Al asignar una enumeración como int, solo esa aplicación (que definió la enumeración) sabe lo que significa en la base de datos. Es como un número mágico en la base de datos ... – dotjoe

+0

Lo siento, borré el primer comentario porque después de volver a leer el código me di cuenta de dónde cometí el error y el comentario no era relevante y el segundo parecía bastante obvio ya que era uno de los primeros éxitos de google, así que pensé que ya lo habías visto. – R0MANARMY

+0

@dotjoe: Eso suena razonable. Sin embargo, había trabajado con versiones anteriores de la biblioteca que hicieron lo contrario (mapeado como int por defecto en vez de cadena), por lo que fue increíblemente confuso para este cambio de comportamiento comenzar a aparecer como lo hizo. – Chris

5

que estoy haciendo lo mismo y tengo trabajo así ...

En mi caso EmployeeType es la clase de enumeración

Map(x => x.EmployeeType, "EmployeeType_Id").CustomType(typeof (EmployeeType)); 
+0

Esto sería perfecto si alguna vez quisiera hacerlo sobre la base de una propiedad específica. – Chris

0

Nunca debe mapear Enum as int en NHibernate. Se convierte en una razón para tener un ghost updates.

La mejor manera de hacerlo es simplemente no establecer una propiedad de tipo en las asignaciones de XML. Para lograr eso en Fluent NHibernate puede usar .CustomType(string.Empty).

Alguna información adicional usted puede encontrar here.

Cuestiones relacionadas