Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 如何修复NHibernate延迟加载错误“;“没有会话或会话已关闭”;?_Asp.net Mvc_Nhibernate_Fluent Nhibernate_Lazy Loading - Fatal编程技术网

Asp.net mvc 如何修复NHibernate延迟加载错误“;“没有会话或会话已关闭”;?

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

我正在用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 { 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();