Daffi
Daffi

Reputation: 516

NHibernate enum Collection Mapping

Im quite new to NHibernate and I am having a question regarding the Mapping of enums in NHibernate (not fluent...).

The Enumeration is:

public enum Setting
{
    CreateUser,
    CreateRole,
    UpdateUser,
    UpdateRole,
    ...
} 

Im also having a class called "Role" which has three attributes:

public class Role
{
    long ID;
    string Name;
    ICollection<Setting> Settings;
}

In this Class Role I want to store all Settings for this special Role. If one Setting is not included in the Collection, then the Role is not allowed to do this actions.

My Problem is now, how to map this class ... . I have already tried to map this relation via Set or Bag but this doenst work quite well.

I could Imagine a Database schema as the following:

+------------+    +------------+    +------------+
| Role       |    | Ref Table  |    | Settings   |
+------------+    +------------+    +------------+
| ID         | FK | Role_ID    | FK | ID         |
| Name       |----| Setting_ID |----| Name       |
+------------+    +------------+    +------------+

Am I rigth so far? Can someone help me how to map this with NHibernate?

so far, thanks

edit 1:

Solved the problem with a seperate enum Class (with ID, Name and a lot of static methods). After that I implemented a many-to-many relationship between Setting and Role.

Upvotes: 1

Views: 854

Answers (2)

Jay
Jay

Reputation: 57939

You might consider using enum FlagsAttribute and bitmask operations here.

You would map NHibernate to a private or protected field that is an integer, and your class would expose a public property representing the collection of Setting values that are read from the flags.

If you are unfamiliar with FlagsAttribute, check out MSDN at http://msdn.microsoft.com/en-us/library/system.flagsattribute(v=vs.110).aspx

Basically, it works like this:

CreateUser = 1,
CreateRole = 2,
UpdateUser = 4,
UpdateRole = 8,
…

These values can be combined in any combination and expressed as an integer. For example, a user with CreateUser and UpdateUser permissions would have a value of 5, and this cannot be expressed by any other combination of Settings.

To my mind, this approach offers the best of both worlds:

  • To the database and NHibernate there is just one integer column -- no additional tables, no foreign keys, no collections, no joins.
  • The public interface in the code remains clean -- no bitmask operations are exposed or required by other classes.

The scenario in which this approach is not favorable is one in which you need to query by Setting, for example "select all users with UpdateRole setting."

Upvotes: 2

Frederik Gheysels
Frederik Gheysels

Reputation: 56934

I think - I haven't tested - you can map your collection of Settings as:

<class name="Role" table="Role">

    <id name="ID" column="ID">
       <generator ... />
    </id>

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

    <set name="Settings table="Ref Table">
      <key column="Role_ID" />
      <element column="Setting_ID" type="int" />
    </set>
</class>

I would map the enum as an integer in the DB. It is perhaps not the very best practice, but it's for the sake of simplicity. Otherwise I think you'll have to create a user defined type in NH, while mapping the numeric value of the integer will do as well. When doing this, you can just define that the collection should be mapped as a set which contains one element, being the Setting. Note that, in this case, I would explicitly specify the numeric values of the Setting enum.

Upvotes: 0

Related Questions