Raven DB – Part 1 – DocumentSession per request with StructureMap

I have been playing with Raven DB of recent and have decided to use it for an application I am writing. Along the way I will write a series of blog posts about it and try to break my relational model mindset.

I am a big fan of the repository and session per request patterns and have been using these when working with NHibernate for the last few years. Whenever I currently implement these patterns with NHibernate I use an IOC container to manage the lifetime of the NHibernate session (per request),  with Raven I decided to do the same to manage the DocumentSession (per request) and also the DocumentStore (singleton).

I am going to make an assumption that as you are reading this you are already familiar with IOC and its general principles.

I use StructureMap as I find it the easiest to work with and also it is as quick as lightening. Firstly we need to manage the lifetime of the DocumentStore. This should only be instantiated once per application so to manage this I wrote a RavenSessionFactoryBuilder which builds the RavenSessionFactory. The RavenSessionFactory accepts an instance of IDocumentStore so I use StructureMap to manage the lifetime of the RavenSessionFactoryBuilder in singleton scope. This means the DocumentStore and the RavenSessionFactory will only be created once per application (first time GetSessionFactory is called – which is basically the first time your application tries to do any kind of document access).

    public class RavenRegistry : Registry
{
public RavenRegistry()
{

ObjectFactory.Configure(x => x.For<IRavenSessionFactoryBuilder>().Singleton()
.Use<RavenSessionFactoryBuilder>());

ObjectFactory.Configure(x => x.For<IDocumentSession>()
.HybridHttpOrThreadLocalScoped()
.AddInstances(inst => inst.ConstructedBy
(context => context.GetInstance<IRavenSessionFactoryBuilder>()
.GetSessionFactory().CreateSession())));
}
}

 

 

    public interface IRavenSessionFactoryBuilder
{
IRavenSessionFactory GetSessionFactory();
}

 

(Please note the Url is set by a custom settings configuration wrapper I wrote and is not part of the Raven Client API)

    public class RavenSessionFactoryBuilder : IRavenSessionFactoryBuilder
{
private IRavenSessionFactory _ravenSessionFactory;

public IRavenSessionFactory GetSessionFactory()
{
return _ravenSessionFactory ?? (_ravenSessionFactory = CreateSessionFactory());
}

private static IRavenSessionFactory CreateSessionFactory()
{
Debug.Write("IRavenSessionFactory Created");
return new RavenSessionFactory(new DocumentStore
{
Url = Settings.DatabaseUrl
});
}
}


Now I needed to manage the DocumentSession and have StructureMap create one instance of this per request. In the RavenRegistry I instructed StructureMap to instantiate a new DocumentSession in HybridHttpOrThreadLocalScoped scope (when used on the web this will create a DocumentSession per http request). StructureMap will construct the DocumentSession by calling on it’s known instance of RavenSessionFactoryBuilder and in turn calling on the instance of RavenSessionFactory to create the DocumentSession by calling the CreateSession method (little bit of a mind bender!).

    public interface IRavenSessionFactory
{
IDocumentSession CreateSession();
}

 

    public class RavenSessionFactory : IRavenSessionFactory
{
private readonly IDocumentStore _documentStore;

public RavenSessionFactory(IDocumentStore documentStore)
{
if (_documentStore == null)
{
_documentStore = documentStore;
_documentStore.Initialise();
}
}

public IDocumentSession CreateSession()
{
Debug.Write("IDocumentSession Created");
return _documentStore.OpenSession();
}
}


For all this code to work correctly our repository’s need to take a constructor argument of  IDocumentSession. I have a base class (PersistentRepository) for all my repositories which in the abstract implementation has a protected IDocumentSession which is instantiated through the constructor.

    public interface IPersistentRepository<T> where T : IPersistable
{
IList<T> GetAll();
T Save(T obj);
T Update(T obj);
void Delete(T obj);
T Get(string id);
T GetFirst();
T GetUnique(Func<T, bool> where);
IList<T> GetRestictedList(Func<T, bool> where);
void DeleteAll(IList<T> objs);
void UpdateAll(IList<T> objs);
void InsertAll(IList<T> objs);
void SaveChanges();
}

 

    public abstract class PersistentRepository<T> : IPersistentRepository<T> where T : IPersistable
{
protected IDocumentSession DocumentSession { get; set; }

protected PersistentRepository(IDocumentSession documentSession)
{
DocumentSession = documentSession;
}
-------------------removed for brevity----------------------
}

 

The UserRepository (and all of my application repositories) are derived from PersistentRepository so now the derived class takes a IDocumentSession as a constructor argument which is passed back down to the base class. So now once you wire in Structuremap to your application every time a repository is used the instantiation of the DocumentSession will be taken care of for you by StructureMap (please note that even if you are calling on two or more different repositories in one http request the same DocumentSession will be used for all instances – perfecto!) .

    public interface IUserRepository
{
void AddUser(User user);
IList<User> GetAll();
}

 

    public class UserRepository : PersistentRepository<User>, IUserRepository
{
public UserRepository(IDocumentSession documentSession) : base(documentSession)
{
}

public void AddUser(User user)
{
Save(user);
SaveChanges();
}
public new IList<User> GetAll()
{
return base.GetAll();
}

}

This is very close to how I currently implement the session per request and repository patterns with NHibernate. In all honesty it was pretty easy to create this implementation of this for use with Raven (due to good design by Ayende rather than my own personal coding skills). Any thoughts or improvements please let me know via comment or email.

Twitter Twitter Twitter Twitter Twitter
June 12, 2010 00:00 by DanWatson

Dependency Injection , Structuremap and ASP.net webforms

I have decided to do a short video cast on dependency injection and ASP.NET webforms after watching Rob Conery’s video on ASP.NET MVC and DI for the Storefront application. I ran into a bunch of problems trying to mimic the behaviour from MVC example to work with webforms. I ended up having to come up with a solution that would work around the whole issue of a webforms page not having a constructor (unlike a MVC controller which does). If you are unfamiliar with structuremap I would recommend watching Rob Conery’s video first to become accustomed with how the library works. You can view the video here.

Please be gentle with the comments this is the first every video cast I have done (and i have flu)!  Ps Its best to view this full screen.

To download the source from this video please click here.  | This work is licensed under a Creative Commons Licence.

Twitter Twitter Twitter Twitter Twitter
April 19, 2009 20:30 by DanWatson