Recently we had the problem of persisting some sort of extended data attached to a business object with the schema and the data of these extended information that can vary over time (usually with an additive strategy). Since we do not need to do extensive or complex analysis queries on these data (they are almost all there for a ‘cosmetic’ fashion) the first thing that came into my mind instead of creating another mapping to a liked table was to use an XML field.

Plus the data that can be stored in this data extension field can be totally different from object to object.

The first step is to find an efficient way to serialize/deserialize objects to our XML format, I made some tests on the standards .net serializers and it came out that the new DataContractSerializer is quite fast compare to the old XmlSerializer, so I decided to give it a try.

Serializing an object is not a real problem, the deserialization step is a little more problematic, mainly because we need to know the type of the object we want to deserialize. but since we want to deserialize some data coming out from a single XML field in a database we do not have this information available...untill we find a way to embed it inside the XML serialized stream.

So the first step was to write a couple of simple functions to serialize a class to an XML stream embedding the type of the serialized item in the outmost tag. This is quite simple to do using the DataContractSerializer functions: WriteStartObject(), WriteObjectContent() and WriteEndObject().

Here’s the code for the serialization helpers, the Type attribute is embedded in a custom attribute called serType:

The last step is now to save and load data using NHibernate, the obvious choice is to use a custom UserType; the serialization and deserialization is done in the NullSafeSet() and NullSafeGet() routines, we also choose to implement the IParameterizedType interface to provide for the KnownTypes that the DataContractSerializer may need in order to deserialize the data in the correct way (a simpler solution is to decorate the classes with the KnownTypeAttribute).

As a note: the DeepClone is actually implemented with a technique already explained in this blog, to be honest it’s not the best way to do it, but it’s a general approach that works well for serializable objects.

To use the previous code, suppose you have the following class hierarchy:

1:publicclass Data

2: {

3:public Guid Id { get; set; }

4:publicstring Data1 { get; set; }

5:// contiene diverse strutture, mappato su campo xml

6:publicobject ExtData { get; set; }

7: }

8:

9: [Serializable]

10:publicclass ExtData

11: {

12:publicstring ExtData1 { get; set; }

13:publicstring ExtData2 { get; set; }

14: }

15:

16: [Serializable]

17:publicclass ExtData2

18: {

19:publicstring ExtData3 { get; set; }

20:publicstring ExtData4 { get; set; }

21: }

with ExtData that can contain instances of data types ExtData and ExtData2 (totally unrelated to each others), you can map the Data class like this: