How to fix a NHibernate lazy loading error “no session or session was closed”?

瘦欲@ 提交于 2019-12-04 10:30:05

Presumably, your GetById is closing the session. This could be explicit, or via a using statement.

A better approach to session management is the Open Session in View pattern. NHibernate sessions are cheap to create, so create one at the start of each request, and close it at the end.

// 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();
}

Using a DI container, we can have the session injected with instances scoped per-request.

// ninject example
Bind<ISession>()
    .ToMethod( ctx => sessionFactory.GetCurrentSession() )
    .InRequestScope();

The session used to get the ig must be alive when accessing ig.Images[1]

I usually do this by instantiating the session before all repository calls, passing the session reference to the the repository constructor and using that reference inside the repository class

I'm not sure if this applies here, but this is (or at least used to be) a common problem in Java MVC frameworks. It usually happens when create the session inside your action. When your action finishes executing, the session object goes out of scope and the session is closed/flushed. Then when the view tries to render the collection of objects you retrieved, it tries to load the lazy-loaded collection using a session that's been closed.

If you're using dependency injection in your project you could have your DI framework instantiate the session for you and pass it as constructor argument into your controller. You could also specify that the DI container should scope the NHibernate session to be the same as your HTTP Request. This will keep the session alive until the request ends (view has finished rendering).

I've used the Autofac as our DI container on a project and work and have been very happy with it.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!