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.
The most obvious way is to introduce ThreadStatic
properties in UnitOfWork
class
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
}
And then in Repository
class:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected ISession Session { get { return UnitOfWork.Current.Session; } }
//other code
}
However I didn't like implementation listed above and decided to find another way to do the same.
So I came with the second way:
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!");
}
}
where ISessionFactory
is singleton resolved by autofac and CurrentSessionContext
is CallSessionContext
.
Then I inject ICurrentSessionProvider
in constructors of UnitOfWork
and Repository
classes and use CurrentSession
property to share sessions.
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?
The best way for you to do this would be to take advantage of the facillities NHibernate already provides to this effect. Please look at section "2.3. Contextual Sessions" on the following documentation: http://nhibernate.info/doc/nh/en/#architecture-current-session
Basically, you need:
This has the advantage that your session handling strategy will be compatible with how it should be done by most NHibernate projects and it doesn't depend on having anything besides an ISessionFactory in the places you want to access the current session.
Forgot to mention: You may of course implement your own ICurrentSessionContext based on the code you already have listed in your question.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With