7

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.

3
  • Email is the string value of the Type property. Nhibernate should be trying to store it as the integer value 1, but it's trying to store the string 'Email' instead, hence the error. I'm not sure why it's doing that though... Commented Apr 11, 2011 at 21:10
  • stackoverflow.com/questions/439003/… Commented Apr 11, 2011 at 21:37
  • or stackoverflow.com/questions/1483044/… Commented Apr 12, 2011 at 8:51

3 Answers 3

5

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));
Sign up to request clarification or add additional context in comments.

1 Comment

This would be perfect if I ever wanted to do it on a property-specific basis.
3

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.

3 Comments

When you map an enum as int, only that app (which defined the enum) knows what it means in the db. It's like a magic number in the database...
Sorry, I deleted the first comment because after re-reading the code realized where I made the mistake and the comment wasn't relevant and the second one seemed kind of obvious as it was one of the first google hits so I figured you'd already seen it.
@dotjoe: That sounds reasonable. I had worked with earlier versions of the library that did the opposite (mapped as int by default rather than string) though, so it was incredibly confusing for this change of behavior to start showing up like it did.
0

You should never map Enum as int in NHibernate. It becomes a reason of having a ghost updates.

The best way to it is just not setting a type property in XML mappings. To achieve that in Fluent NHibernate you can use .CustomType(string.Empty).

Some additional info you can find here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.