Unit of work setup using Ninject and Ravendb

Unit of work setup using Ninject and Ravendb

This is an example of setting up RavenDb using Ninject, Unit of work style. There are a number of different approaches out there, many using an abstract base controller. But this one is inspired by a castle based solution i stumbled upon wich i liked.

The first thing you need to setup is the nuget packages. What you need are the ‘Ninject.MVC3’ and ‘RavenDB.Client.MvcIntegration’ basically (presuming you are using a standalone RavenDB server).
When this is taken care of we start by verifying, and if needed add, the connectionstring to your web.config. It should look something like the following (192.168.1.1 = your server ip):

<connectionStrings>
 <add name="RavenDB" connectionString="Url=http://192.168.1.1:8081;Database=somedb;user=someuser;password=somepassword" />
 </connectionStrings>

When this is done, we can proceed and bind RavenDB:s store and session using ninject. Open App_Start\NinjectWebCommon.cs in your main web project and then add the following to the RegisterServices method:

private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind().ToMethod(context =>
            {
                var documentStore = new DocumentStore { ConnectionStringName = "RavenDB" };
                return documentStore.Initialize();
            }).InSingletonScope();
            kernel.Bind().ToMethod(context => context.Kernel.Get().OpenSession()).InRequestScope();
        }
    }

This will, as seen in the code, bind a documentstore as a singleton scope and the session (wich is what we need to work against the database) in requestscope.
Now you will be able to inject IDocumentSession into your controllers / services. But we want to have a unit of work approach to this so lets continue.

The approach we will be using is a modification of a solution wich source i unfortunately cannot remember(if anyone know, please post link and ill include it) wich means we will create a global actionfilter. This will then be executed at the end of each request, performing a SaveChanges().

The first thing we need is to create a new class, where is just a matter of your project organizing preferences. This class will then be made to look something like this:

namespace SampleProject.Filters
{
    [AttributeUsage(AttributeTargets.Class, Inherited = true)]
    public class RavenDbSessionAttribute : FilterAttribute, IActionFilter
    {
        public void OnActionExecuting(ActionExecutingContext filterContext) {}

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (filterContext.Exception == null)
            {
                using (var session = DependencyResolver.Current.GetService())
                    session.SaveChanges();
            }
        }
    }
}

The last step is then to register our actionfilter. Locate, and open, the file App_Start\FilterConfig.cs then we add the filter like this:

using System.Web;
using System.Web.Mvc;
using SampleProject.Filters;

namespace SampleProject
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new RavenDbSessionAttribute());
        }
    }
}

Thats all and if everything worked as planned your entity changes should now be saved without the need of calling SaveChanges()!

One thought on “Unit of work setup using Ninject and Ravendb

Leave a Reply

Your email address will not be published. Required fields are marked *