【问题标题】:ASP.NET NHibernate - failed to lazily initialize a collection no session or session was closedASP.NET NHibernate - 无法延迟初始化集合,没有会话或会话已关闭
【发布时间】:2016-01-26 02:18:27
【问题描述】:

我在 ASP.NET WebForms 应用程序上使用 NHibernate 时遇到了一些问题。

我可以做所有事情 - 保存、获取、删除、更新寄存器,但是当我尝试使用惰性集合获取一些对象时,会引发异常:

会话已关闭

我什么都试过了。有人可以帮忙吗?

存储库类

    private ISession m_session = NHibernateHelper.OpenSession();

    protected ISession Session
    {
        get
        {
            return m_session;
        }
    }

    public virtual void Update(T entity)
    {
        using (ITransaction transaction = Session.BeginTransaction())
        {
            Session.Merge(entity);
            transaction.Commit();
        }
    }

    public virtual int Count()
    {
        return (from t in Session.Query<T>()
                select t).Count();
    }

    public virtual void Remove(T entity)
    {
        using (ISession session = NHibernateHelper.OpenSession())
            try
            {
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Delete(entity);
                    transaction.Commit();
                }
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
    }

    public virtual void Remove(int id)
    {
        using (ISession session = NHibernateHelper.OpenSession())
            try
            {
                T entity = session.Get<T>(id);
                using (ITransaction transaction = session.BeginTransaction())
                {
                    session.Delete(entity);
                    transaction.Commit();
                }
            }
            catch (Exception e)
            {

                throw new Exception(e.Message);


            }
    }

    public virtual IList<T> ListAll()
    {
        return (from t in Session.Query<T>()
                select t).ToList();
    }

    public virtual T Get(Type entityType, object id)
    {
        return (T)Session.Get(entityType, id);
    }

    public virtual T Get(object id)
    {
        return Session.Get<T>(id);
    }

    public virtual void Save(T entity)
    {
        using (ISession session = NHibernateHelper.OpenSession())
        using (ITransaction transaction = session.BeginTransaction())
        {
            session.Save(entity);
            transaction.Commit();
        }
    }

NHibernateHelper

public class NHibernateHelper
{
    private static ISessionFactory _sessionFactory = null;

    private static ISessionFactory GetSessionFactory()
    {
        return CreateSessionFactory();
    }

    private static Object createLock = new Object();

    private static ISessionFactory CreateSessionFactory()
    {
        lock (createLock)
        {

            if (_sessionFactory == null)
            {

                Configuration config = new Configuration().Configure(System.Reflection.Assembly.GetExecutingAssembly(), "Repositorio.hibernate.cfg.xml");
                _sessionFactory = config.BuildSessionFactory();
            }


            return _sessionFactory;
        }
    }

    public static ISession OpenSession()
    {
        return GetSessionFactory().OpenSession();
    }
}

【问题讨论】:

  • 答案是正确的,但答案提供的解决方案不是一个好方法。您需要一个 Open Session In View 模式。你可以搜索并找到很多关于它的东西。

标签: c# asp.net nhibernate lazy-loading


【解决方案1】:

我没有将会话管理放在我的存储库中。可能发生的情况是您从打开会话的存储库中获取项目列表,然后将对象传递回控制器(页面/视图或您设计的任何内容)。但是当控制器获取项目时,您已经完成了 repo 的工作并且它已经关闭了会话。 在您的控制器中,您点击了惰性属性,但由于会话已关闭,您会得到惰性异常。 为了使惰性属性可用,您需要将对象附加到实时会话,直到您完成工作单元。因此,您可以在将它们交给控制器之前点击 repo 中的惰性属性(有点违背惰性的目的),或者您可以将会话控制放在链的更高位置。

我的 http 请求负责会话,并使用 RequestHttpModule 在每个请求的生命周期内创建一个活动会话(无论我是否需要)。这样,当视图控制器遇到惰性属性时,该对象仍会附加到实时会话以获取惰性对象。 您可以为“每个请求的休眠会话”使用“Bing”,您会发现一些详细介绍该模式的博客。

我的请求模块如下所示:

public class RequestHttpModule : IHttpModule {
        public void Init(HttpApplication context) {
            context.BeginRequest += new EventHandler(ContextBeginRequest);
            context.EndRequest += new EventHandler(ContextEndRequest);
        }

        public void Dispose() { }

        public void ContextBeginRequest(Object sender, EventArgs e) {
            SessionManager.GetInstance().OpenSession();
        }

        public void ContextEndRequest(Object sender, EventArgs e) {
            SessionManager.GetInstance().DisposeCurrentSession();
        }
}

然后在Web.config中注册模块

<system.webServer>
    <modules>
      <add name="RequestHttpModule" type="MyWebApp.RequestHttpModule" />
    </modules>
  </system.webServer>

}

【讨论】:

    猜你喜欢
    • 2014-11-02
    • 1970-01-01
    • 2011-12-11
    • 1970-01-01
    • 2011-03-31
    • 2011-07-18
    • 1970-01-01
    • 2017-10-08
    • 2011-03-03
    相关资源
    最近更新 更多