NHibernate throwing Session is closed

2020-07-18 03:57发布

问题:

I'm flapping in the wind, so I thought I'd ask here... Please let me know if this is obvious and has been answered before.

I'm building an MVC 3 site which works fine while I'm running it with one user, where I click through the pages. However, if I madly hit refresh, eventually I hit a "Session is closed".

I've isolated out almost all of all my repository to try to get to the bottom, so I know have it erroring on the homepage. The only thing that is being called in the repository is get the user's name from a database table.

I'm using Postgres as a database, and the ASP.NET Membership provider from NauckIT. The main database is also Postgres (but another database).

The session management is done using the following code:

public class MvcApplication : System.Web.HttpApplication
{
    public static ISessionFactory SessionFactory = 
             NHibernateHelper.GetSessionFactory();

    public MvcApplication()
    {
        this.BeginRequest += MvcApplication_BeginRequest;
        this.EndRequest += MvcApplication_EndRequest;
    }

    void MvcApplication_BeginRequest(object sender, EventArgs e)
    {
        CurrentSessionContext.Bind(SessionFactory.OpenSession());
    }
    void MvcApplication_EndRequest(object sender, EventArgs e)
    {            
        CurrentSessionContext.Unbind(SessionFactory).Dispose();
    }
}

The code that get's the login information is:

    public Login GetCurrentLogin()
    {
        return Session.Query<Login>().FirstOrDefault(l => l.UserID == UserAccessRepository.UserID);
    }

The UserAccessRepository simply gets the userid from the forms authentication cookie.

Session is injected into the repository using:

        ninjectKernel.Bind<IUserRepository>().To<NHUserRepository>();
        ninjectKernel.Bind<ILeagueRepository>().To<NHLeagueRepository>().InThreadScope();
        ninjectKernel.Bind<ISession>()
            .ToMethod(m => MvcApplication.SessionFactory.GetCurrentSession())

The sessionfactory comes from:

public class NHibernateHelper
{
    private static ISessionFactory _sessionFactory;

    public static ISessionFactory SessionFactory
    {
        get
        {
            if (_sessionFactory == null)
            {       var rawConfig = new Configuration();
                rawConfig.SetNamingStrategy(new PostgresNamingStrategy());
                var configuration = Fluently.Configure(rawConfig)
                    .Database(PostgreSQLConfiguration.Standard.ConnectionString(ConnectionString).ShowSql().Dialect("NHibernate.Dialect.PostgreSQL82Dialect"))
                    .Mappings(m =>
                                m.AutoMappings.Add(AutoMap.AssemblyOf<Event>(new AutoMapConfiguration())
                )).ExposeConfiguration(cfg => 
                    cfg.SetProperty("current_session_context_class", "web")
                _sessionFactory = configuration.BuildSessionFactory();
                Debug.WriteLine("Built SessionFactory");
            }
            return _sessionFactory;

To be clear, it works fine in the standard instance where I click through the pages, but when I madly hit F5, I get the session closed issue.

UPDATE: Not sure if it's relevant, but the main place I'm seeing this in the BaseController, from within the OnActionExecuting method. It seems to have cleared up in the methods above.

回答1:

You should not be using InThreadScope() in a web app. Use InRequestScope(). EDIT Have a read of Object Scopes - its been updated recently and not knowing it backwards is going to waste your time sooner or later!

If you're looking to make stuff work across a membership provider and request processing, you need to search for Ninject Custom Provider (maybe something like here).