Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate, SQL Server - enum to int mapping

I have a class that has an enum type indicating whether the message type is Email or Sms. The enum type is defined:

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

The class that utilizes this type looks like:

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

When I try to persist an entity of type Reminder to the database however, I get the following error:

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

The backing field is of type int, so I'm not sure why NHibernate is trying to map the string representation by default. I'm using Fluent NHibernate, and the relevant mapping code is:

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

I'm pretty sure the default behavior of NHibernate is to map enums as ints, so why is it not doing so in this case? I'm using SQL Server 2005, if that matters.

like image 715
Chris Avatar asked Apr 11 '11 21:04

Chris


2 Answers

I am doing the same thing and got it working like so...

In my case EmployeeType is the enum class

 Map(x => x.EmployeeType, "EmployeeType_Id").CustomType(typeof (EmployeeType));
like image 105
Todd Avatar answered Nov 03 '22 00:11

Todd


I don't know why this person keeps posting and then deleting their comment or answer, but the link they provided () does answer my question. I opted not to go with a full blow class definition for the convention, but rather, an inline convention in the mappings code, like so:

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

The last convention builder statement did the trick. I'm curious as to why Fluent NHibernate's default is to map enums as strings now. That doesn't seem to make much sense.

like image 24
Chris Avatar answered Nov 03 '22 00:11

Chris