Asp.net mvc 如何修复NHibernate延迟加载错误“;“没有会话或会话已关闭”;?
我正在用ASP.NET MVC、NHibernate和Fluent Hibernate开发一个网站,当我尝试访问子对象时,出现错误“没有会话或会话已关闭” 以下是我的域类:Asp.net mvc 如何修复NHibernate延迟加载错误“;“没有会话或会话已关闭”;?,asp.net-mvc,nhibernate,fluent-nhibernate,lazy-loading,Asp.net Mvc,Nhibernate,Fluent Nhibernate,Lazy Loading,我正在用ASP.NET MVC、NHibernate和Fluent Hibernate开发一个网站,当我尝试访问子对象时,出现错误“没有会话或会话已关闭” 以下是我的域类: public class ImageGallery { public virtual int Id { get; set; } public virtual string Title { get; set; } public virtual IList<Image> Images { ge
public class ImageGallery {
public virtual int Id { get; set; }
public virtual string Title { get; set; }
public virtual IList<Image> Images { get; set; }
}
public class Image {
public virtual int Id { get; set; }
public virtual ImageGallery ImageGallery { get; set; }
public virtual string File { get; set; }
}
但是,当我尝试使用此代码访问图像子对象时
string imageFile = ig.Images[1].File;
我得到这个错误:
初始化[Entities.ImageGallery#1]-未能延迟初始化角色集合:Entities.ImageGallery.Images,未关闭任何会话或会话
有人知道我该怎么解决这个问题吗
多谢各位
编辑
我的GetById方法是:
public ImageGallery GetById(int id) {
using(ISession session = NHibernateSessionFactory.OpenSession()) {
return session.Get<ImageGallery>(id);
}
}
公共图像库GetById(int id){
使用(ISession session=NHibernateSessionFactory.OpenSession()){
返回会话.Get(id);
}
}
当访问
ig.Images[1]
我通常通过在所有存储库调用之前实例化会话,将会话引用传递给存储库构造函数,并在存储库类中使用该引用来实现这一点。这可以是显式的,也可以通过using语句 一种更好的会话管理方法是视图中的开放会话模式。NHibernate会话的创建成本很低,因此在每个请求开始时创建一个会话,并在请求结束时关闭它
// in global.asax.cs
public void Application_Start()
{
BeginRequest += delegate {
CurrentSessionContext.Bind( sessionFactory.OpenSession());
};
EndRequest += delegate {
var session = sessionFactory.GetCurrentSession();
if (null != session) {
session.Dispose();
}
CurrentSessionContext.Unbind(sessionFactory);
};
}
// in your NHibernateSessionFactory class
public static ISession OpenSession() {
return SessionFactory.GetCurrentSession();
}
使用DI容器,我们可以在会话中注入每个请求范围内的实例
// ninject example
Bind<ISession>()
.ToMethod( ctx => sessionFactory.GetCurrentSession() )
.InRequestScope();
//ninject示例
绑定()
.ToMethod(ctx=>sessionFactory.GetCurrentSession())
.InRequestScope();
我不确定这是否适用于这里,但这是(或至少过去是)Java MVC框架中的一个常见问题。通常在操作中创建会话时发生。当您的操作完成执行时,会话对象超出范围,会话被关闭/刷新。然后,当视图尝试呈现检索到的对象集合时,它会尝试使用已关闭的会话加载延迟加载的集合
如果在项目中使用依赖项注入,可以让DI框架为您实例化会话,并将其作为构造函数参数传递到控制器中。您还可以指定DI容器应该限定NHibernate会话的范围,使其与HTTP请求相同。这将使会话保持活动状态,直到请求结束(视图已完成渲染)
我在一个项目和工作中使用了作为我们的DI容器,并对此非常满意。您忘记发布从数据库检索对象并操纵会话的
GetById
方法。@MCardinale-我发现这仍然没有一个可接受的答案。你绕过这个了吗?我遇到了同样的问题,下面的答案没有帮助。+1对于视图模式中的Open Session,我记不起名称。该模式让我印象深刻的一点是(取决于FlushMode),您可以在视图渲染代码中修改实体。这就是你为了不把所有东西都投射到DTO而冒的风险吗?非常感谢。我问了另一个问题(),希望有人帮我做这件事,因为我不知道怎么做。@LachlanRoche在这里的例子中,当你在DI容器中进行绑定时,sessionFactory
来自哪里?我现在正在努力解决这个问题。在回购调用之前,您如何以及在何处实例化会话?在控制器上?你什么时候结束会议?非常感谢。
public ImageGallery GetById(int id) {
using(ISession session = NHibernateSessionFactory.OpenSession()) {
return session.Get<ImageGallery>(id);
}
}
// in global.asax.cs
public void Application_Start()
{
BeginRequest += delegate {
CurrentSessionContext.Bind( sessionFactory.OpenSession());
};
EndRequest += delegate {
var session = sessionFactory.GetCurrentSession();
if (null != session) {
session.Dispose();
}
CurrentSessionContext.Unbind(sessionFactory);
};
}
// in your NHibernateSessionFactory class
public static ISession OpenSession() {
return SessionFactory.GetCurrentSession();
}
// ninject example
Bind<ISession>()
.ToMethod( ctx => sessionFactory.GetCurrentSession() )
.InRequestScope();