c# - 在 UnitOfWork 和 Repository 之间共享一个 NHibernate session

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

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

这两种方法似乎都运作良好。所以我想知道还有其他方法可以实现吗?在工作单元和存储库之间共享 session 的最佳做法是什么?

最佳答案

您执行此操作的最佳方法是利用 NHibernate 已经提供的功能来实现此效果。 请查看以下文档中的“2.3. 上下文 session ”部分:http://nhibernate.info/doc/nh/en/#architecture-current-session

基本上,您需要:

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

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

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

关于c# - 在 UnitOfWork 和 Repository 之间共享一个 NHibernate session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29239793/

相关文章:

c# - Azure CosmosDB Contains 方法不起作用

C# 用户输入设置数组大小和循环数组显示元素

c# - NHibernate 3.0 和 LINQ : what am I missing?

Mercurial - 如何推送未完成的分支?

maven - 如果在 settings.xml 中配置了镜像,则项目存储库将被忽略

git - GitHub 中的项目与存储库

c# - Entity Framework 在哪里存储属性名称和它在 SQL 中选择的列之间的映射?

C# Windows 服务文本编写器

c# - NHibernate - 如何处理 NonUniqueObjectException?

c# - NHibernate 连接和投影属性