tags:

views:

1323

answers:

4

Take the following Enum Flag

[Flags]
enum Permssions
{
   CanComment = 1,
   CanEdit = 2,
   CanDelete = 4,
   CanRemoveUsers = 8,
   All = CanComment | CanEdit | CanDelete | CanRemoveUsers 
}

In NHibernate I have mapped to a enum before using:

<property type="n.Permssions, n.Permssions"
name="Permssions" column="Permssions"></property>

My question is, how do I map a bitwise field to a Flag field using NHibnerate?

+1  A: 

I think the best option for this would be to use a Custom User Type. In which you could map the Enum in your class to those two columns. Here is an example of using ICompositeUserMap which can be used as a guide:

Although in your case, just implementing IUserType could suffice.

gcores
Did I just get downvoted for some stupid reputation thing?
gcores
A: 

This doesn't answer your question exactly, but it might be easier to use an Int32 property in your class and mapping, and use a static class of constants like this to handle the values in code:

public static class Permissions
{
    public const int CanComment = 0x1;
    public const int CanEdit = 0x2;
    public const int CanDelete = 0x4;
    public const int CanRemoveUsers = 0x8;
    public const int All = CanComment | CanEdit | CanDelete | CanRemoveUsers;
}

I know this is not ideal, since it doesn't restrict your users to the fixed enum values, and forces you to deal with raw ints in code, but I think Hibernate will have trouble with a bitwise enum. It will try to map a value in the database back to a specific enum value. If it finds a value in the database which you have not explicitly enumerated it will probably choke. E.g. if it finds a "3" in the database, it won't be able to map it back to an enum value, unless you explicitly enumerate every combination, like CanCommentAndEdit, CanCommentAndEditAndDelete, etc. This probably defeats the purpose of using the bitwise enum.

Andy White
A: 

I would have a private int field for the NHibernate persistence and a public Getter/Setter property for the flag enum that read and write to the int field. (NHibernate can be configured to work with private fields)

That way you don't have to resort to voodoo magic or messy constants to get the job done.

AndreasKnudsen
+6  A: 

When I map an enum, and this enum has a backing value of type 'int', I just map my enum property to an int field in the database. I haven't run into problems for this.
I have done this for flag enums as well, and this just works without problems. When you combine certain flags, NHibernate will persist the 'combination' of those flags into the specified column in the database.
When you retrieve the instance that has a property of 'flag enums', then NHibernate will reconstitute it back to the correct combination.
For instance, if the DB contains '3', then NHibernate will populate your property with the combination of the apropriate values.
In fact, I let NHibernate figure it out all by himself:

<property name="OnCallType" column="OnCallType" />

where the OnCallType column is of type int in my DB, and the OnCallType property is an enumerated type that has the flags attribute.

Frederik Gheysels