State Pattern, Enumeration Class and Fluent NHibernate (Oh my!)
Recently, I needed to change a basic enumeration into a full-fledged state pattern. After getting all my domain classes updated, I began reviewing the persistence layer. And I hit a wall. I wasn’t sure how I wanted to update my Fluent NHibernate convention to persist the current state.
My original classes were similar to this:
public class MyProgress{ public virtual Guid Id { get; set; } ...
... public virtual MyStatus Status { get; private set; }}
public enum MyStatus{ New, InProgress, Completed, Canceled, Failed}
My new state pattern was similar to this:
public abstract class MyStatus{ public static readonly MyStatus New = new NewStatus(); public static readonly MyStatus InProgress = new InProgressStatus();
...}public class NewStatus: MyStatus { public override void Start(MyProgress progress) { progress.SetStatus(InProgress); } public override void Cancel(MyProgress progress) { progress.SetStatus(Cancelled); } public override void Fail(MyProgress progress) { progress.SetStatus(Failed); }}...
Here is the problem… My enumeration was persisted as an integer field on the record. Now that I had a state pattern, how should I save my state? I googled the problem and found Derick Bailey’s article on the state pattern and Fluent NHibernate. Derick’s pattern works well, but I felt that creating a lookup table in my database just so I can persist a value in another table was not the path I wanted to traverse – I wasn’t persisting an entity, I was persisting a state value on an entity. Not finding any more love from Google, I asked around and was advised to contact fellow Elegant Coder and Guild3 member, Jason Grundy. Here is Jason’s advice:
"I’ve recently changed from using Enums to an approach outlined by Jimmy Bogard here. In the Entity I would do something like this:
protected int _orderStatusId;public virtual OrderStatus OrderStatus{ get { return Enumeration.FromValue<OrderStatus>(_orderStatusId); } set { _orderStatusId = value.Value; } }Then in Fluent NH you can simply map to the protected member."
I decided to pursue Jason’s advice. The result is my database tables did not need to change at all. Here is some snippets of the updated classes:
public class MyProgress { public virtual Guid Id {get;set;} ... protected int _status; public virtual MyStatus { get{ return Enumeration.FromValue<MyStatus>(_status); } set{ _status = value.Value; } } ... }
public class MyStatus : Enumeration { public static MyStatus New = new NewStatus(); ...
private class NewStatus : MyStatus { public NewStatus() : base (0,"New")
public override void Start(MyProgress progress) { progress.SetStatus(InProgress); } } ...
Notice that the MyStatus class is no longer abstract. However, the subclasses are all private nested classes, each with a value and a display name. I set each subclass value to match the enumeration value it replaced. I did not need to convert my existing data to a new schema.
And here is the Fluent NHibernate override:
public class MyProgressOverride : IAutoMappingOverride<MyProgress>{ public void Override(AutoMapping<MyProgress> mapping) { mapping.Map(x => x.Status) .CustomType(typeof(int)) .Access.CamelCaseField(Prefix.Underscore); }}
As you can see, we use convention-based automapping with overrides, but this same map could be used in a standard class map.
Thanks to Jimmy, Derick, and Jason for the inspiration and assistance!

