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

Cof*_*fka 6 c# nhibernate repository unit-of-work autofac

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

最明显的方法ThreadStaticUnitOfWork课堂上介绍属性

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
}
Run Code Online (Sandbox Code Playgroud)

然后在Repository课堂上:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    protected ISession Session { get { return UnitOfWork.Current.Session; } }

    //other code
}
Run Code Online (Sandbox Code Playgroud)

但是我不喜欢上面列出的实现,并决定找到另一种方法来做同样的事情.

所以我带来了第二种方式:

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!");
    }
}
Run Code Online (Sandbox Code Playgroud)

这里ISessionFactory是由单解决autofac和CurrentSessionContextCallSessionContext.然后我注入ICurrentSessionProvider构造函数UnitOfWorkRepository类,并使用CurrentSession属性来共享会话.

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

Fre*_*oux 1

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

基本上,您需要:

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

这样做的优点是,您的会话处理策略将与大多数 NHibernate 项目的执行方式兼容,并且它不依赖于在您想要访问当前会话的位置中除了 ISessionFactory 之外的任何内容。

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