在UnitOfWork和Repository之间共享一个NHibernate会话

时间:2015-03-24 18:03:20

标签: c# nhibernate repository autofac unit-of-work

我试图用NHibernate实现UnitOfWork和Repository模式。我正在寻找在工作单元实例和存储库实例之间共享会话的最佳方法。

最明显的方式是在ThreadStatic类中引入UnitOfWork属性

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解析的单身,CurrentSessionContextCallSessionContext。 然后我在ICurrentSessionProviderUnitOfWork类的构造函数中注入Repository并使用CurrentSession属性来共享会话。

这两种方法似乎都运转正常。所以我想知道有没有其他方法来实现这个?在工作单元和存储库之间共享会话的最佳实践是什么?

1 个答案:

答案 0 :(得分:0)

这样做的最佳方式是利用NHibernate已经为此提供的便利。 请查看以下文档中的“2.3。上下文会话”部分:http://nhibernate.info/doc/nh/en/#architecture-current-session

基本上,你需要:

  1. ICurrentSessionContext接口的合适实现,可满足您的需求。
  2. 通知SessionFactory您要使用该实现。
  3. 将ISessionFactory(您的会话工厂)注入您需要访问“当前会话”的任何地方。
  4. 使用sessionFactory.GetCurrentSession()。
  5. 获取当前会话

    这样做的好处是,您的会话处理策略将与大多数NHibernate项目应该如何完成兼容,并且它不依赖于您想要访问当前会话的地方除了ISessionFactory之外的任何内容。

    忘记提及:您当然可以根据您在问题中列出的代码实现自己的ICurrentSessionContext。