Home > View Post

Prevalence

I mentioned prevalence in the final installment of The awesome power of IoC series of posts and said I'd talk about it in more detail. We could all write a simple object storage mechanism that simply serializes an object graph to disk and, any time a change is made and needs to be persisted, we reserialize and overwrite (e.g. a List<Customer> instead of a Customer Table in a database). This would work fine on an infinitessimally small scale but as soon as the object graph grows, the expense of serializing a number of objects would blow this approach out of the water.

The idea behind Prevalence is that the whole object graph is only persisted at certain points in time, called Snapshots. In between snapshots we just record the changes made to the object graph. Now the approach becomes much more workable.

There is a .NET prevalence engine called Bamboo and written by a chap called Rodrigo B. de Oliveira. (If you installed the Castle.msi file from The Awesome Power of IoC posts you'll already have the assembly).

The idea is that Bamboo needs to proxy a specific class that is used to make changes to the repository - which is naturally going to look a bit like some kind of data access layer:

public class CustomerDal : MarshalByRefObject
{
    public virtual void InsertCustomer(Customer customer)
    {
        // add the customer object to the object graph
    }
    
    public virtual void DeleteCustomer(int id)
    {
        // delete the customer from the object graph
    }
    
    public virtual void UpdateCustomer(Customer customer)
    {
        // Update the customer in the object graph
        // Caution - be sure to use the customer id
        // because the reference may not be the same!
    }
    
    [Query]
    public virtual Customer GetCustomer(int id)
    {
        // Get the customer from the object graph
    }
}

You probably noticed that our CustomerDal inherits from MarshalByRefObject. Inheriting from MarshalByRefObject allows calls to be intercepted (remoting uses the same technique) so that every call can be recorded, serializing the parameters, to be replayed later. Notice that we decorated the GetCustomer method with the [Query] attribute to indicate that there's no point recording these calls.

So the next time the Prevalence engine is asked to load up a particular object graph, it will deserialize the latest snapshot and then replay any subsequent changes through the CustomerDal class. Very clever. You just need to strike a balance between the cost of saving frequent snapshots vs the cost of replaying a lot of changes. Clearly, you don't need to throw away your SQL books just yet. This technology isn't built for the big time and I'm yet to find a production use for it (for a start, there's no way of horizontally scaling out, not to mention the lack of atomic transactions etc). However, it has been useful for little demo applications because it saved me from creating a database and writing/generating the data access code (as demonstrated in the IoC example). The IoC example code is still available so why not check out the source and have a look at how Bamboo is used.

I'm sure there are some killer applications out there for this concept - just not sure what yet.

Tags: Other

 
Josh Post By Josh Twist
4:52 AM
13 Dec 2006

» Next Post: Copying from Message Boxes
« Previous Post: Smuggling Headers with WCF

Comments are closed for this post.

© 2005 - 2017 Josh Twist - All Rights Reserved.