I have a class defined like this:
public class StateMachineMetadata<T> where T: struct
{
public virtual int ID { get; protected set; }
public virtual T State { get; set; }
public virtual DateTime DateChanged { get; set; }
}
Where the State property is an enum:
public enum CarState
{
Stopped = 1,
Moving = 2
}
public enum OrderState
{
Ordered = 1,
Delivered = 2
}
Can I have two types:
StateMachineMetadata<CarState>, StateMachineMetadata<OrderState>
to be persisted in one table StateMachineMetadata using NHibernate?
=== update ===
As workaround generic part can be moved to interface:
public interface IStateMachineMetadata<T> where T: struct
{
int ID { get; }
T State { get; set; }
DateTime DateChanged { get; set; }
}
public class StateMachineMetadataBase
{
public virtual int ID { get; protected set; }
public virtual DateTime DateChanged { get; set; }
}
public class CarStateMachineMetadata
: StateMachineMetadataBase, IStateMachineMetadata<CarState>
{
public virtual CarState State { get; set; }
}
No, and here’s why.
Let’s assume we have two rows in the
StateMachineMetadatatable:If the
Statecolumn is mapped both toCarStateandOrderState, how would NHibernate determine which enum to deserialize to? One solution would be to add a discriminator column to theStateMachineMetadatatable, which tells NHibernate which type it should map a specific row to.For example the
Typediscriminator column:tells NHibernate that the first row represents a
StateMachineMetadata<CarState>while the second is aStateMachineMetadata<OrderState>. This is called a Table per class hierarchy mapping in NHibernate. It requires both classes to inherit from a common base class, which in your case would naturally beStateMachineMetadata<T>.But here’s the catch: NHibernate doesn’t have a way to map a class with an open generic type. The reason is that it’s simply not possible.
However, NHibernate does allow you to map classes with closed generics. You just can’t map them to the same table. Here’s how such configuration would look like: