我正在尝试使用 NHibernate 实现 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
类的构造函数中注入(inject) ICurrentSessionProvider
并使用 CurrentSession
属性来共享 session 。
这两种方法似乎都运作良好。所以我想知道还有其他方法可以实现吗?在工作单元和存储库之间共享 session 的最佳做法是什么?
最佳答案
您执行此操作的最佳方法是利用 NHibernate 已经提供的功能来实现此效果。 请查看以下文档中的“2.3. 上下文 session ”部分:http://nhibernate.info/doc/nh/en/#architecture-current-session
基本上,您需要:
- 满足您需求的 ICurrentSessionContext 接口(interface)的合适实现。
- 通知 SessionFactory 您要使用该实现。
- 将 ISessionFactory(您的 session 工厂)注入(inject)到您需要访问“当前 session ”的任何地方。
- 使用 sessionFactory.GetCurrentSession() 获取当前 session 。
这样做的好处是,您的 session 处理策略将与大多数 NHibernate 项目应该如何完成它兼容,并且它不依赖于在您想要访问当前 session 的地方除了 ISessionFactory 之外的任何东西。
忘记提及:您当然可以根据问题中已列出的代码实现自己的 ICurrentSessionContext。
关于c# - 在 UnitOfWork 和 Repository 之间共享一个 NHibernate session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29239793/