Jovan Perovic
Jovan Perovic

Reputation: 20191

C# String enum as NHibernate discriminator

I have this case that can't really get to work. Basically, I have abstract class User and extended classes Admin, Teacher and LabEmployee. Here are my mappings:

<class name="User" table="users" dynamic-update="true" dynamic-insert="true" select-before-update="false">
<id name="Id">
  <column name="id" sql-type="bigint"/>
  <generator class="identity"/>
</id>
<discriminator column="user_type" type="String"/>
...
some irrelevant properties (username, password, email etc.)
...
<subclass name="Admin" discriminator-value="ADMIN"/>
<subclass name="LabEmloyee" discriminator-value="LABEMPLOYEE"/>
<subclass name="Teacher" discriminator-value="TEACHER"/>
</class>

Now, I would really like to use this Enum

 public enum UserType
 {
     ADMIN, LABEMPLOYEE, TEACHER
 }

I understand that Nhibernate by default maps enums to integers so ADMIN would be "0", LABEMPLOYEE would be "1" and TEACHER would be "2". I tried following this post:

http://codebetter.com/jefferypalermo/2006/03/14/using-enum-strings-with-nhibernate-persistence-level-400/

... and defined UserTypeWrapper:

public class UserTypeWrapper: NHibernate.Type.EnumStringType
{
    public UserTypeWrapper()
        : base(typeof(User.UserType))
    {
    }
}

... but it assumes that enum is not discriminator, that is, I can't set discriminator type as UserTypeWrapper as NHibernate throws MappingException "Could not determine type for: UserTypeWrapper".

Does anyone know how to achieve this?

Any help would be greatly appreciated! Thanks!

Upvotes: 3

Views: 2354

Answers (1)

Firo
Firo

Reputation: 30813

discriminator value is nowhere seen in the classes therefor you dont need any usertype to convert from db to property. in the hbm you also cant use the enum, you have to write the value directly in discriminator-value="". What you want is probably:

abstract class User
{
    public virtual UserType Type { get; protected set;}
}

class Teacher : User
{
    public Teacher()
    {
        Type = UserType.Teacher;
    }
}

class LabEmployee : User
{
    public LabEmployee()
    {
        Type = UserType.LabEmployee;
    }
}

switch(someuser.Type)

or using a convention

abstract class User
{
    public virtual UserType Type { get; protected set;}

    public User()
    {
        Type = Enum.Parse(typeof(UserType), this.GetType().Name);
    }
}

and to use a convention for the value in the mapping as well (Fluent NHibernate convention to specify the discriminator value)

public class DiscriminatorValueConvention : ISubclassConvention
{
    public void Apply(ISubclassInstance instance)
    {
        instance.DiscriminatorValue(instance.EntityType.Name);
    }
}

Upvotes: 5

Related Questions