确保Repository和UnitOfWork类共享同一个nhibernate会话对象的正确方法是什么?

时间:2012-09-29 04:29:49

标签: asp.net-mvc nhibernate session ninject

我在编辑和删除对象时遇到问题,我认为这是因为我没有在我的存储库类和我的unitofwork类之间共享相同的会话对象。我试图找到一些关于连接它的最佳方法的文档,所以我共享相同的会话对象。

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

3 个答案:

答案 0 :(得分:5)

我通常将会话设置为存储库的依赖项,因此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实现已经是工作类的一个单元。

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

如果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;
    }
}

和IOC代码:

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

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

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

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