views:

102

answers:

4

What approach should I take when serializing an object to the database, keeping in mind that the objects properties will change in time?

At first, I thought of making sure all my objects implement an interface, but what happens when an interface looses a property and gains another. What happeneds to the existing serialized data in the database upon restoration?

Should I use abstract classes or interfaces? Best approach people have used.

Thank you

A: 

what will the life time of the objects be? if it was only short term you could use datasets and update the properties on the fly.

Euclid
DataSets use lots of memory which I'd like to avoid. Thanks for suggestion anyway :)
Vince
+2  A: 

The partial implementation below may give you some ideas for flexibly storing and retrieving properties. For managing property addition and removal, when you add properties no problem. When you drop properties you could not allow new properties of that type to be created in the future but preserve existing data or remove all data associated with those properties.

/// <summary>
/// The data storage could look something like this
/// create table PersistedObject (ObjectId int )
/// create table PersistedProperty (PropertyId int , PropertyName varchar(50) )
/// create table Data (ValueId int, PropertyId int, SerializedValue image )
/// </summary>
interface IFlexiblePersistence
{
    object this[string propertyName] { get; set;}

    void Persist();

}

class Person : IFlexiblePersistence
{
    Dictionary<string, object> data;

    public Person(int personId)
    {
        data = PopulatePersonData(personId);
    }

    public object this[string propertyName]
    {
        get { return data[propertyName]; }

        set
        {
            data[propertyName] = value;
            Persist();
        }
    }

    public void Persist()
    {
        LoopThroughAllValuesAndSaveToDB();
    }
}
David Silva Smith
I like your implementation. Basically an encapsulator of properties seems like the ideal solution for my situation.
Vince
+1  A: 

That's a time honored question with no one correct answer.

It depends greatly on how the data will be used in your application. The amount of RAM you'll want to cap the use at, as well as the anticipated largest size for your database. All of those factors will push you toward or away from various approaches.

  1. This article discusses datatables and their use within that specific app.

  2. This article discusses the use of data transfer objects.

  3. This forum discussion gives many opinions on data transfer objects vs domain modeling.

Approaches 2 and 3 above are fully compatible with David Silva Smiths IFlexiblePersistence approach listed in his reply. However, you potentially use more memory and lose much of the performance gains from doing the "typical" DTO. If memory and speed aren't a concern, his approach will likely be very simple.

Jason D
+1  A: 

It depends what you mean by "serialization" (it is an overloaded term). If you mean your existing object as columns, then and ORM: EF, LINQ-to-SQL, NHibernate, etc. If you mean your object as a single varbinary(max) / varchar(max):

Whatever else you do, don't use BinaryFormatter - this will break if you change the fields (for example, changing a regular property into an auto-property). You need something contract-based, most of which will be fine with changes. Suggestions:

  • XmlSerializer / DataContractSerializer / Json.NET (text)
  • protobuf-net (binary, uses google's "protocol buffers" wire format)

With the above you can generally use pretty standard DTOs; for example (compatible with DataContractSerializer and protobuf-net):

[DataContract]
public class Customer {
    [DataMember(Order=1)]
    public int {get;set;}

    [DataMember(Order=2)]
    public string Name {get;set;}
}

I wouldn't use NetDataContractSerializer for similar reasons to BinaryFormatter - fine for short-lived requests, but not good for storage. Note that most serializers use concrete classes, since very few include the type metadata in the output (and hence would need additional configuration to tie ICustomer to your Customer class).

Marc Gravell