title: Sharing a NHibernate session between UnitOfWork and Repository
body: <p>I'm trying to implement UnitOfWork and Repository pattern with NHibernate. I'm looking for the best way to share session between unit of work instance and repository instance.</p>
  
  <p><strong>The most obvious way</strong> is to introduce <code>ThreadStatic</code> properties in <code>UnitOfWork</code> class</p>
  
  <pre><code>public class UnitOfWork : IUnitOfWork
  {
      public static UnitOfWork Current
      {
          get { return _current; }
          set { _current = value; }
      }
      [ThreadStatic]
      private static UnitOfWork _current;
  
      public ISession Session { get; private set; }
  
      //other code
  }
  </code></pre>
  
  <p>And then in <code>Repository</code> class:</p>
  
  <pre><code>public class Repository&lt;TEntity&gt; : IRepository&lt;TEntity&gt; where TEntity : class
  {
      protected ISession Session { get { return UnitOfWork.Current.Session; } }
  
      //other code
  }
  </code></pre>
  
  <p>However I didn't like implementation listed above and decided to find another way to do the same.</p>
  
  <p>So I came <strong>with the second way</strong>:</p>
  
  <pre><code>public interface ICurrentSessionProvider : IDisposable
  {
      ISession CurrentSession { get; }
      ISession OpenSession();
      void ReleaseSession();
  }
  
  public class CurrentSessionProvider : ICurrentSessionProvider
  {
      private readonly ISessionFactory _sessionFactory;
  
      public CurrentSessionProvider(ISessionFactory sessionFactory)
      {
          _sessionFactory = sessionFactory;
      }
  
      public ISession OpenSession()
      {
          var session = _sessionFactory.OpenSession();
          CurrentSessionContext.Bind(session);
          return session;
      }
  
      public void Dispose()
      {
          CurrentSessionContext.Unbind(_sessionFactory);
      }
  
      public ISession CurrentSession
      {
          get
          {
              if (!CurrentSessionContext.HasBind(_sessionFactory))
              {
                  OnContextualSessionIsNotFound();
              }
              var contextualSession = _sessionFactory.GetCurrentSession();
              if (contextualSession == null)
              {
                  OnContextualSessionIsNotFound();
              }
              return contextualSession;
          }
      }
  
      private static void OnContextualSessionIsNotFound()
      {
          throw new InvalidOperationException("Session is not opened!");
      }
  }
  </code></pre>
  
  <p>where <code>ISessionFactory</code> is singleton resolved by autofac and <code>CurrentSessionContext</code> is <code>CallSessionContext</code>.
  Then I inject <code>ICurrentSessionProvider</code> in constructors of <code>UnitOfWork</code> and <code>Repository</code> classes and use <code>CurrentSession</code> property to share sessions.</p>
  
  <p>Both approaches seem to be working fine. So I'm wondering are there any other ways to implement this? What is the best practice in sharing session between unit of work and repository?</p>