我正在尝试使用NHibernate实现UnitOfWork和Repository模式。我正在寻找在UnitOfWork实例和Repository实例之间共享session的最佳方法。
最明显的方法是在UnitOfWork
类中引入ThreadStatic
属性。
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
}
接着,在Repository
类中:
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected ISession Session { get { return UnitOfWork.Current.Session; } }
//other 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!");
}
}
其中ISessionFactory
是由autofac解析的单例,而CurrentSessionContext
是CallSessionContext
。然后我在UnitOfWork
和Repository
类的构造函数中注入了ICurrentSessionProvider
,并使用CurrentSession
属性来共享会话。
这两种方法似乎都可以正常工作。所以我想知道还有没有其他实现方式?在工作单元和仓储之间共享会话的最佳实践是什么?