I have a simple ASP.NET MVC web application that uses NHibernate with FluentNHibernate’s auto mapping feature for its data access. I have encountered a scenario in which I would like NHibernate to persist some classes as binary data.
For example, I have something similar to this:
public class User
{
...
// This field will be persisted
public virtual byte[] PortraitData { get; set; }
// This method will get me what I'm actually interested in
public virtual Image GetPortrait()
{
return SerializationHelper.Deserialize<Image>(PortraitData);
}
}
(I leave the implementation of the SerializationHelper class to the reader’s imagination. It doesn’t do anything complicated, just serializes and deserializes data into byte arrays and back.)
I would like to change the above code to this:
public class User
{
...
public virtual Image Portrait { get; set; }
}
So basically I wish to tell (Fluent)NHibernate that it should persist some classes (specified by me) by serializing them into a binary field with the name of the actual property.
(In the above case, I would like it to serialize the Image into a varbinary field called Portrait.)
The actual scenario I have is a bit more complicated than this, but this example demonstrates very well what I want to achieve. (Meaning: the System.Drawing.Image class is not the only one I’m interested in serializing.)
I know there must be some kind of configuration in either Fluent or NHibernate itself that allows to do exactly this, but I couldn’t figure it out. Could you please tell me how to do this?
Thanks in advance for your help!
The key is an implementation of IUserType, which is essentially an interface you use to translate back and forth from a POCO type to a SQL type. I use it to translate enumerations <-> custom string values in the database. Take a look at the NHibernate code for YesNoType, which translates back and forth between true/false booleans POCO types to “YES”/”NO” SQL varchar types.
To utilize this in Fluent NHibernate, you can invoke the .CustomType() method on the Map method, where T is the class that implements IUserType. I think you could create a convention such that all Image properties would use the implementing class, rather than having to define it on a per-property basis, but I’m not familiar with that part of Fluent NHibernate.
e.g. Map(x => x.Portrait, “PORTRAIT_DATA”).CustomType();