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



我在编辑和删除对象时遇到问题,我认为这是因为我的存储库类和工作单元类之间没有共享相同的会话对象。我正试图找到一些关于连接这一点的最佳方式的文档,以便共享同一个会话对象。

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

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

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

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

http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-当前会话

如果Robin的答案对你不起作用,你可能对Ninject有错误配置。

今天早上,我遇到了一个非常类似的问题,并进行了更新。在我的例子中,我从一个会话中读取对象,该会话绑定到一个范围与我正在写入的会话不同的对象

这是我的简单会话提供者:

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"/>将模块添加到web.config中
  3. 如果您使用的是较新的Ninject,它在<add name="OnePerRequestHttpModule" type="Ninject.Web.Common.OnePerRequestHttpModule, Ninject.Web.Common"/>

最新更新