title: Implementing UnitOfWork with Castle.Windsor
body: <p>Simple question.</p>
  
  <blockquote>
    <p><strong>How do I use UnitOfWork with Castle.Windsor, nHibernate, and ASP.NET MVC?</strong></p>
  </blockquote>
  
  <p>Now for the extended details. In my quest to understand the <code>UnitOfWork</code> pattern, I'm having difficulty coming across anything that uses a direct example in conjunction with <code>Castle.Windsor</code>, specifically in regards to the way it needs to be installed. </p>
  
  <p>Here is my understanding so far.</p>
  
  <h2>IUnitOfWork</h2>
  
  <ul>
  <li>The <code>IUnitOfWork</code> interface is used to declare the pattern</li>
  <li>The <code>UnitOfWork</code> class must <code>Commit</code> and <code>Rollback</code> transactions, and Expose a <code>Session</code>.</li>
  </ul>
  
  <p>So with that said, here is my <code>IUnitOfWork</code>. (I am using <code>Fluent nHibernate</code>)</p>
  
  <pre><code>public interface IUnitOfWork : IDisposable
  {
      ISession Session { get; private set; }
      void Rollback();
      void Commit();
  }
  </code></pre>
  
  <p>So here is my <code>Castle.Windsor</code> Container Bootstrapper (ASP.NET MVC)</p>
  
  <pre><code>public class WindsorContainerFactory
  {
      private static Castle.Windsor.IWindsorContainer container;
      private static readonly object SyncObject = new object();
  
      public static Castle.Windsor.IWindsorContainer Current()
      {
          if (container == null)
          {
              lock (SyncObject)
              {
                  if (container == null)
                  {
                      container = new Castle.Windsor.WindsorContainer();
  
                      container.Install(new Installers.SessionInstaller());
                      container.Install(new Installers.RepositoryInstaller());
                      container.Install(new Installers.ProviderInstaller());
                      container.Install(new Installers.ControllerInstaller());
                  }
              }
  
          }
  
          return container;
      }
  }
  </code></pre>
  
  <p>So now, in my <code>Global.asax</code> file, I have the following...</p>
  
  <pre><code>    protected void Application_Start()
      {
          AreaRegistration.RegisterAllAreas();
  
          RegisterGlobalFilters(GlobalFilters.Filters);
          RegisterRoutes(RouteTable.Routes);
  
          // Register the Windsor Container
          ControllerBuilder.Current
              .SetControllerFactory(new Containers.WindsorControllerFactory());
      }
  </code></pre>
  
  <h2>Repository</h2>
  
  <p>Now I understand that I need to pass the <code>ISession</code> to my Repository. So then, let me assume <code>IMembershipRepository</code>.</p>
  
  <pre><code>class MembershipRepository : IMembershipRepository
  {
     private readonly ISession session;
     public MembershipRepository(ISession session)
     {
        this.session = session;
     }
  
     public Member RetrieveMember(string email)
     {
        return session.Query&lt;Member&gt;().SingleOrDefault( i =&gt; i.Email == email );
     }
  }
  </code></pre>
  
  <p>So I am confused, now. Using this method, the <code>ISession</code> doesn't get destroyed properly, and the <code>UnitOfWork</code> never gets used. </p>
  
  <p>I've been informed that <code>UnitOfWork</code> needs to go in the Web Request Level - but I cannot find anything explaining how to actually go about this. I do not use a <code>ServiceLocator</code> of any sort ( as when I tried, I was told this was also bad practice... ).</p>
  
  <blockquote>
    <blockquote>
      <p>Confusion -- How does a <code>UnitOfWork</code> get created?</p>
    </blockquote>
    
    <p>I just don't understand this, in
    general. My thought was that I would
    start passing <code>UnitOfWork</code> into the
    <code>Repository</code> constructors - but if it
    has to go in the Web Request, I'm not
    understanding where the two relate.</p>
  </blockquote>
  
  <h2>Further Code</h2>
  
  <p>This is extra code for clarification, simply because I seem to have a habit of never providing the right information for my questions.</p>
  
  <h2>Installers</h2>
  
  <pre><code>public class ControllerInstaller : IWindsorInstaller
  {
      public void Install(IWindsorContainer container, IConfigurationStore store)
      {
          container.Register(
              AllTypes.FromThisAssembly()
              .BasedOn&lt;IController&gt;()
              .Configure(c =&gt; c.LifeStyle.Transient));
      }
  }
  
  public class ProviderInstaller : IWindsorInstaller
  {
      public void Install(IWindsorContainer container, IConfigurationStore store)
      {
          container.Register(
              Component
              .For&lt;Membership.IFormsAuthenticationProvider&gt;()
              .ImplementedBy&lt;Membership.FormsAuthenticationProvider&gt;()
              .LifeStyle.Singleton
          );
      }
  }
  
  public class RepositoryInstaller : IWindsorInstaller
  {
      public void Install(IWindsorContainer container, IConfigurationStore store)
      {
          container.Register(
              Component
              .For&lt;Membership.IMembershipRepository&gt;()
              .ImplementedBy&lt;Membership.MembershipRepository&gt;()
              .LifeStyle.Transient
          );
  
          container.Register(
              Component
              .For&lt;Characters.ICharacterRepository&gt;()
              .ImplementedBy&lt;Characters.CharacterRepository&gt;()
              .LifeStyle.Transient
          );
      }
  }
  
  public class SessionInstaller : Castle.MicroKernel.Registration.IWindsorInstaller
  {
      private static ISessionFactory factory;
      private static readonly object SyncObject = new object();
  
      public void Install(Castle.Windsor.IWindsorContainer container, IConfigurationStore store)
      {
          container.Register(
              Component.For&lt;ISessionFactory&gt;()
                  .UsingFactoryMethod(SessionFactoryFactory)
                  .LifeStyle.Singleton
              );
  
          container.Register(
              Component.For&lt;ISession&gt;()
              .UsingFactoryMethod(c =&gt; SessionFactoryFactory().OpenSession())
              .LifeStyle.Transient
          );
      }
  
      private static ISessionFactory SessionFactoryFactory()
      {
          if (factory == null)
              lock (SyncObject)
                  if (factory == null)
                      factory = Persistence.SessionFactory.Map(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["Remote"].ConnectionString);
          return factory;
      }
  }
  </code></pre>
  
  <h2>UnitOfWork</h2>
  
  <p>Here is my <code>UnitOfWork</code> class verbatim.</p>
  
  <pre><code>public class UnitOfWork : IUnitOfWork
  {
      private readonly ISessionFactory sessionFactory;
      private readonly ITransaction transaction;
  
      public UnitOfWork(ISessionFactory sessionFactory)
      {
          this.sessionFactory = sessionFactory;
          Session = this.sessionFactory.OpenSession();
          transaction = Session.BeginTransaction();
      }
  
      public ISession Session { get; private set; }
  
      public void Dispose()
      {
          Session.Close();
          Session = null;
      }
  
      public void Rollback()
      {
          if (transaction.IsActive)
              transaction.Rollback();
      }
  
      public void Commit()
      {
          if (transaction.IsActive)
              transaction.Commit();
      }
  }
  </code></pre>