【问题标题】:What is the right way to ensure your Repository and UnitOfWork class share the same nhibernate session object?确保您的 Repository 和 UnitOfWork 类共享相同的休眠会话对象的正确方法是什么?
【发布时间】:2012-09-20 22:09:14
【问题描述】:

我在编辑和删除对象时遇到问题,我认为这是因为我没有在我的存储库类和我的 unitofwork 类之间共享相同的会话对象。我正在尝试找到一些有关将其连接起来的最佳方式的文档,因此我共享相同的会话对象。

我在 mvc 网站中使用 ninject 作为我的 IOC 容器。

【问题讨论】:

  • 这个问题真的需要更多关注吗?如果您将 ISession 而不是 ISessionFactory 注入您的工作单元,Ninject 在同一个会话中传递。

标签: asp.net-mvc nhibernate session ninject


【解决方案1】:

Nhibernate 有一个共享会话的内置机制,即上下文。根据应用程序,您可以使用适当的上下文。欲知详情,

http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session

【讨论】:

    【解决方案2】:

    如果 Robin 的回答不适合您,您可能对 Ninject 的配置有误。

    今天早上我在更新时遇到了一个非常相似的问题。在我的情况下,我正在从会话中读取对象,该会话绑定到与我正在写入的会话不同范围内的对象。

    这是我的简单 SessionProvider:

    public class SessionProvider : Provider<ISession>
    {
        protected override ISession CreateInstance(IContext context)
        {
            var factory = context.Kernel.Get<ISessionFactory>();
            var session = factory.OpenSession();
            return session;
        }
    }
    

    和国际奥委会代码:

            kernel.Bind<ISessionFactory>().ToProvider<SessionFactoryProvider>();
            kernel.Bind<ISession>().ToProvider<SessionProvider>().InRequestScope();
    

    确保您的工作单元和存储库都使用相同的 ISession 实例化的最简单方法是确保它们也在请求范围内创建。但是,这应该是默认设置。

    根据您安装 NInject 的方式和使用的版本,您可能必须安装 HTTP 模块以确保请求范围正常工作:

    1. 如果你安装了 NuGet 包,它会添加DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
    2. 如果您有旧版本的 Ninject,您还可以使用 &lt;add name="OnePerRequestModule" type="Ninject.Core.Behavior.OnePerRequestModule, Ninject.Core"/&gt; 将模块添加到 web.config
    3. 如果您使用的是较新的 Ninject,它位于 &lt;add name="OnePerRequestHttpModule" type="Ninject.Web.Common.OnePerRequestHttpModule, Ninject.Web.Common"/&gt;

    【讨论】:

      【解决方案3】:

      我一般把session设置为repository的依赖,这样Ninject就可以解决依赖(ISession = NHibernate.ISession):

      public UserRepository(ISession session)
      {
          ...
      }
      

      这是我设置绑定的方式:

      kernel.Bind<ISession>().ToMethod(x => GetRequestSession()).InRequestScope();
      

      因此,当需要会话时,Ninject 将调用 GetRequestSession() 来检索会话。函数实现如下:

      private static ISession GetRequestSession()
              {
                  IDictionary httpContextItems = HttpContext.Current.Items;
      
                  ISession session;
                  if (!httpContextItems.Contains(MvcApplication.SESSION_KEY))
                  {
                      // Create an NHibernate session for this request
                      session = MvcApplication.SessionFactory.OpenSession();
                      httpContextItems.Add(MvcApplication.SESSION_KEY, session);
                  }
                  else
                  {
                      // Re-use the NHibernate session for this request
                      session = (ISession)httpContextItems[MvcApplication.SESSION_KEY];
                  }
                  return session;
              }
      

      NHibernate 会话存储在 HttpContext 项中。这是一个键值集合,可用于在处理一个请求期间存储和共享数据。

      每个请求只创建一次会话,并在请求期间重复使用。

      MvcApplication.SESSION_KEY 只是我在 Global.asax 中定义的一个常量字符串,以便能够从 HttpContext 存储和检索会话。此外,会话工厂位于 global.asax 中,并在启动时创建。

      您的工作单元类也可以将 ISession 设置为依赖项,因此 Ninject 也会解决此依赖项,因此使用相同的会话。另一方面,您可能不需要工作单元类,因为 NHibernate 的 ISession 实现本身已经是一个工作单元类。

      我不确定这是否是最佳做法,但它对我来说非常有效。

      【讨论】:

      • 这取决于您的工作单元类是如何实现的。例如,如果它是控制器上的一个属性,您可以让 Ninject 将会话注入到该属性中。您还可以使会话依赖于您的工作单元类,并让存储库依赖于工作单元类。 Ninject 将为您处理依赖链。基本上归结为让 Ninject 担心在必要时创建会话。
      • 这里列出了我的 unitofwork 类代码:stackoverflow.com/questions/12552761/…
      • 不是在 unitofwork 类的构造函数中使用 ISessionFactory,而是在构造函数中使用 ISession。 Ninject 会调用 GetRequestSession 方法来检索会话,当在 httpcontext 中没有找到会话时会调用 sessionfactory。这意味着每个请求只有一个会话。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      相关资源
      最近更新 更多