在UnitOfWork和Repository之间共享NHibernate会话

6

我正在尝试使用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解析的单例,而CurrentSessionContextCallSessionContext。然后我在UnitOfWorkRepository类的构造函数中注入了ICurrentSessionProvider,并使用CurrentSession属性来共享会话。

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

1个回答

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。


希望您能提供一个设置这个特定架构的代码示例! - adaam
嘿,我现在有点赶,但也许以下非常简化的示例可以帮助您入门(稍后再看是否可以更新):https://gist.github.com/anonymous/ebd36d4a39c2ed45dd20824d849f89f7 - Fredy Treboux

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接