4

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

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

4

3 回答 3

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 实现本身已经是一个工作单元类。

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

于 2012-09-29T12:44:49.140 回答
2

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

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

于 2012-09-29T12:21:16.280 回答
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;
    }
}

和国际奥委会代码:

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

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

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

  1. 如果您安装了 NuGet 包,它将添加DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
  2. 如果您有旧版本的 Ninject,您还可以使用将模块添加到 web.config<add name="OnePerRequestModule" type="Ninject.Core.Behavior.OnePerRequestModule, Ninject.Core"/>
  3. 如果您使用的是较新的 Ninject,它位于<add name="OnePerRequestHttpModule" type="Ninject.Web.Common.OnePerRequestHttpModule, Ninject.Web.Common"/>
于 2012-10-06T04:24:17.280 回答