NHibernate的,和奇数QUOT;会话关闭&QUOT!;错误 [英] NHibernate, and odd "Session is Closed!" errors

查看:156
本文介绍了NHibernate的,和奇数QUOT;会话关闭&QUOT!;错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注:现在,我已经输入了这一点,我对超级长的问题道歉,但我认为所有的code和这里psented信息$ P $是一些相关的方法。

好吧,我让奇在我的ASP.NET web表单应用程序会话关闭的错误,在任意点。然而,今天,它终于在同一个地方遍地再次发生。我一定附近,没有什么被处理或在我的code会议结束时,作为使用的都是很好包含所有其他code,你会看到下面的远code的位。

Okay, I'm getting odd "Session Is Closed" errors, at random points in my ASP.NET webforms application. Today, however, it's finally happening in the same place over and over again. I am near certain that nothing is disposing or closing the session in my code, as the bits of code that use are well contained away from all other code as you'll see below.

我还使用ninject作为我国际奥委会,这可能/可能并不重要。

I'm also using ninject as my IOC, which may / may not be important.

好了,所以,我首先 SessionFactoryProvider SessionProvider 类:

Okay, so, First my SessionFactoryProvider and SessionProvider classes:

SessionFactoryProvider

public class SessionFactoryProvider : IDisposable
{
    ISessionFactory sessionFactory;

    public ISessionFactory GetSessionFactory()
    {
        if (sessionFactory == null)
            sessionFactory =
                Fluently.Configure()
                        .Database(
                            MsSqlConfiguration.MsSql2005.ConnectionString(p =>
                                p.FromConnectionStringWithKey("QoiSqlConnection")))
                        .Mappings(m =>
                            m.FluentMappings.AddFromAssemblyOf<JobMapping>())
                        .BuildSessionFactory();

        return sessionFactory;
    }

    public void Dispose()
    {
        if (sessionFactory != null)
            sessionFactory.Dispose();
    }
}


SessionProvider


SessionProvider

public class SessionProvider : IDisposable
{
    ISessionFactory sessionFactory;
    ISession session;

    public SessionProvider(SessionFactoryProvider sessionFactoryProvider)
    {
        this.sessionFactory = sessionFactoryProvider.GetSessionFactory();
    }

    public ISession GetCurrentSession()
    {
        if (session == null)
            session = sessionFactory.OpenSession();

        return session;
    }

    public void Dispose()
    {
        if (session != null)
        {
            session.Dispose();                
        }
    }
}


这两个类与Ninject接线像这样:


These two classes are wired up with Ninject as so:

NHibernateModule

NHibernateModule

public class NHibernateModule : StandardModule
{        
    public override void Load()
    {
        Bind<SessionFactoryProvider>().ToSelf().Using<SingletonBehavior>();
        Bind<SessionProvider>().ToSelf().Using<OnePerRequestBehavior>();
    }
}


而据我可以告诉按预期方式工作。


and as far as I can tell work as expected.

现在我的 BaseDao&LT; T&GT; 类:

BaseDao

BaseDao

public class BaseDao<T> : IDao<T> where T : EntityBase
{
    private SessionProvider sessionManager;
    protected ISession session { get { return sessionManager.GetCurrentSession(); } }

    public BaseDao(SessionProvider sessionManager)
    {
        this.sessionManager = sessionManager;
    }        

    public T GetBy(int id)
    {
        return session.Get<T>(id);
    }

    public void Save(T item)        
    {
        using (var transaction = session.BeginTransaction())
        {
            session.SaveOrUpdate(item);

            transaction.Commit();
        }
    }

    public void Delete(T item)
    {
        using (var transaction = session.BeginTransaction())
        {
            session.Delete(item);

            transaction.Commit();
        }
    }

    public IList<T> GetAll()
    {
        return session.CreateCriteria<T>().List<T>();
    }

    public IQueryable<T> Query()
    {
        return session.Linq<T>();
    }        
}


这势必在Ninject像这样:


Which is bound in Ninject like so:

DaoModule

DaoModule

public class DaoModule : StandardModule
{
    public override void Load()
    {
        Bind(typeof(IDao<>)).To(typeof(BaseDao<>))
                            .Using<OnePerRequestBehavior>();
    }
}


现在,是造成这是当我节省的对象,直到我做了一些模型变化今天没发生了,但是改变我的模式没有改变的数据访问code。在Web请求无论如何。虽然换了几个NHibernate的映射(我可以发布这些太多,如果有人有兴趣)


Now the web request that is causing this is when I'm saving an object, it didn't occur till I made some model changes today, however the changes to my model has not changed the data access code in anyway. Though it changed a few NHibernate mappings (I can post these too if anyone is interested)

这是据我所知, BaseDao&LT; SomeClass的&GT;不用彷徨被称为然后 BaseDao&LT; SomeOtherClass&GT;不用彷徨被称为然后 BaseDao&LT; TypeImTryingToSave方式&gt; .Save 被称为

From as far as I can tell, BaseDao<SomeClass>.Get is called then BaseDao<SomeOtherClass>.Get is called then BaseDao<TypeImTryingToSave>.Save is called.

这是在该行的第三次调用保存()

using (var transaction = session.BeginTransaction())

这是失败,会话关闭!或者说异常:

that fails with "Session is Closed!" or rather the exception:

Session is closed!
Object name: 'ISession'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ObjectDisposedException: Session is closed!
Object name: 'ISession'.

的确以下通过调试器显示会话从要求第三次 SessionProvider 这的确是关闭并没有连接。

And indeed following through on the Debugger shows the third time the session is requested from the SessionProvider it is indeed closed and not connected.

我已经验证了的Dispose 我的 SessionFactoryProvider 和我的 SessionProvider 被称为在请求结束,而不是之前的保存呼叫在吾道的。

I have verified that Dispose on my SessionFactoryProvider and on my SessionProvider are called at the end of the request and not before the Save call is made on my Dao.

所以,现在我有点卡住了。有几件事情突然在脑海中。

So now I'm a little stuck. A few things pop to mind.


  • 我是明明做错什么?

  • 并没有NHibernate的问我要?
  • 曾经接近会议
  • 在我可以做什么的任何变通办法或想法?

  • Am I doing anything obviously wrong?
  • Does NHibernate ever close sessions without me asking to?
  • Any workarounds or ideas on what I might do?

在此先感谢

推荐答案

ASP.NET是多线程的,以便访问的ISession必须是线程安全的。假设你正在使用的session-per-要求,要做到这一点最简单的方法就是使用NHibernate的内置的上下文相关的会话的。

ASP.NET is multi-threaded so access to the ISession must be thread safe. Assuming you're using session-per-request, the easiest way to do that is to use NHibernate's built-in handling of contextual sessions.

首先配置NHibernate的使用web会话的上下文类:

First configure NHibernate to use the web session context class:

sessionFactory = Fluently.Configure()
    .Database(
        MsSqlConfiguration.MsSql2005.ConnectionString(p =>
            p.FromConnectionStringWithKey("QoiSqlConnection")))
    .Mappings(m => m.FluentMappings.AddFromAssemblyOf<JobMapping>())
    .ExposeConfiguration(x => x.SetProperty("current_session_context_class", "web")
    .BuildSessionFactory();

然后使用 ISessionFactory.GetCurrentSession()来获取现有会话,或者一个新的会话,如果不存在绑定到工厂。下面,我将削减+粘贴我的code打开和关闭会话。

Then use the ISessionFactory.GetCurrentSession() to get an existing session, or bind a new session to the factory if none exists. Below I'm going to cut+paste my code for opening and closing a session.

    public ISession GetContextSession()
    {
        var factory = GetFactory(); // GetFactory returns an ISessionFactory in my helper class
        ISession session;
        if (CurrentSessionContext.HasBind(factory))
        {
            session = factory.GetCurrentSession();
        }
        else
        {
            session = factory.OpenSession();
            CurrentSessionContext.Bind(session);
        }
        return session;
    }

    public void EndContextSession()
    {
        var factory = GetFactory();
        var session = CurrentSessionContext.Unbind(factory);
        if (session != null && session.IsOpen)
        {
            try
            {
                if (session.Transaction != null && session.Transaction.IsActive)
                {
                    session.Transaction.Rollback();
                    throw new Exception("Rolling back uncommited NHibernate transaction.");
                }
                session.Flush();
            }
            catch (Exception ex)
            {
                log.Error("SessionKey.EndContextSession", ex);
                throw;
            }
            finally
            {
                session.Close();
                session.Dispose();
            }
        }
    }        

这篇关于NHibernate的,和奇数QUOT;会话关闭&QUOT!;错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆