我以为这是我的课,所以我试图使用不同的方法从这个博客文章http://pwigle.wordpress.com/2008/11/21/nhibernate-session-handling-in-aspnet-the-easy-way/,但我仍然得到相同的问题.我得到的实际错误是:
Server Error in '/AvvioCMS' Application. Failed to lazily initialize a collection,no session or session was closed 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: NHibernate.LazyInitializationException: Failed to lazily initialize a collection,no session or session was closed
无论是否打开数据库,但这是主要的祸根.
我把会话管理类放在下面,任何人都可以发现为什么我可能会遇到这些问题?
public interface IUnitOfWorkDataStore { object this[string key] { get; set; } } public static Configuration Init(IUnitOfWorkDataStore storage,Assembly[] assemblies) { if (storage == null) throw new Exception("storage mechanism was null but must be provided"); Configuration cfg = ConfigureNHibernate(string.Empty); foreach (Assembly assembly in assemblies) { cfg.AddMappingsFromAssembly(assembly); } SessionFactory = cfg.BuildSessionFactory(); ContextDataStore = storage; return cfg; } public static ISessionFactory SessionFactory { get; set; } public static ISession StoredSession { get { return (ISession)ContextDataStore[NHibernateSession.CDS_NHibernateSession]; } set { ContextDataStore[NHibernateSession.CDS_NHibernateSession] = value; } } public const string CDS_NHibernateSession = "NHibernateSession"; public const string CDS_IDbConnection = "IDbConnection"; public static IUnitOfWorkDataStore ContextDataStore { get; set; } private static object locker = new object(); public static ISession Current { get { ISession session = StoredSession; if (session == null) { lock (locker) { if (DBConnection != null) session = SessionFactory.OpenSession(DBConnection); else session = SessionFactory.OpenSession(); StoredSession = session; } } return session; } set { StoredSession = value; } } public static IDbConnection DBConnection { get { return (IDbConnection)ContextDataStore[NHibernateSession.CDS_IDbConnection]; } set { ContextDataStore[NHibernateSession.CDS_IDbConnection] = value; } } }
我正在使用的实际商店是这样的:
public class HttpContextDataStore : IUnitOfWorkDataStore { public object this[string key] { get { return HttpContext.Current.Items[key]; } set { HttpContext.Current.Items[key] = value; } } }
我在Application_Start上初始化SessionFactory:
NHibernateSession.Init(new HttpContextDataStore(),new Assembly[] { typeof(MappedClass).Assembly});
更新
嗨,嗨,谢谢你的建议,我尝试了一些不同的东西来尝试和简化代码,但我仍然遇到同样的问题,我可能有一个想法为什么.
我根据需要创建会话,但是在我的global.asax中,我正在处理Application_EndRequest上的会话.不过我发现Application_EndRequest在加载页面结束时正在调试中被多次触发.我认为这个事件只是在请求的最后一次启动,但是如果没有,而其他一些项目正试图使用Session(这是什么错误的抱怨),无论什么奇怪的原因,可能是我的问题,会话仍然是线程安全,它只是被提前处理.
任何人有任何想法?我做了一个谷歌,看到VS开发服务器确实造成这样的问题,但是我通过IIS运行它.
解决方法
You should observe the following
practices when creating NHibernate
Sessions:
Never create more than one concurrent
ISession or ITransaction instance per
database connection.Be extremely careful when creating
more than one ISession per database
per transaction. The ISession itself
keeps track of updates made to loaded
objects,so a different ISession might
see stale data.The ISession is not threadsafe! Never
access the same ISession in two
concurrent threads. An ISession is
usually only a single unit-of-work!
最后一点是我所说的最相关(对于多线程环境而言很重要).一个ISession应该用于一个小的原子操作,然后处理.还从文档中:
An ISessionFactory is an
expensive-to-create,threadsafe object
intended to be shared by all
application threads. An ISession is an
inexpensive,non-threadsafe object
that should be used once,for a single
business process,and then discarded.
结合这两个想法,而不是存储ISession本身,存储会话工厂,因为那是“大”对象.然后,您可以使用类似SessionManager.GetSession()作为包装器从会话存储中检索工厂,并实例化一个会话并将其用于一个操作.
在ASP.NET应用程序的上下文中,问题也不太明显.您正在静态地定义ISession对象,这意味着它在AppDomain之间共享.如果在AppDomain的生命周期内创建了两个不同的页面请求并且同时执行,那么现在有两个页面(不同的线程)触及相同的ISession,这是不安全的.
基本上,尽量不要尽可能长时间地进行会议,尽量摆脱困难,看看是否有更好的效果.
编辑:
好的,我可以看到你想要去哪里.听起来你正在尝试实现Open Session In View模式,并且可以使用几种不同的路线:
如果添加另一个框架不是一个问题,请查看像Spring.NET.这是模块化的,所以你不必使用整个事情,你可以使用NHibernate帮助模块.它支持视图模式下的开放会话.文件here(标题21.2.10.“网络会话管理”).
如果你宁愿自己滚动,请查看Bill McCafferty发布的这个代码项目:“NHibernate Best Practices”.最后,他描述了通过自定义IHttpModule实现模式.我也看过互联网上的帖子来实现没有IHttpModule的模式,但这可能是你一直在尝试的.
我通常的模式(也许你已经在这里跳过了)首先使用框架.它消除了许多头痛.如果它太慢或不符合我的需要,那么我尝试调整配置或定制它.只有在此之后,我才试图滚动自己,但是YMMV. 原文链接:https://www.f2er.com/aspnet/250005.html