I've been using NHibernate for a while now and have found from time to time that if I try to request two pages simultaniously (or as close as I can) it will occasionally error. So I assumed that it was because my Session management was not thread safe.
I thought it was my class so I tried to use a different method from this blog post http://pwigle.wordpress.com/2008/11/21/nhibernate-session-handling-in-aspnet-the-easy-way/ however I still get the same issues. The actual error I am getting is:
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
Either that or no datareader is open, but this is the main culprit.
I've placed my session management class below, can anyone spot why I may be having these issues?
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;
}
}
}
And the actual store I am using is this:
public class HttpContextDataStore : IUnitOfWorkDataStore
{
public object this[string key]
{
get { return HttpContext.Current.Items[key]; }
set { HttpContext.Current.Items[key] = value; }
}
}
I initialize the SessionFactory on Application_Start up with:
NHibernateSession.Init(new HttpContextDataStore(), new Assembly[] {
typeof(MappedClass).Assembly});
Update
Hi guys, thanks for your advice, I have tried a few different things to try and simplify the code but I am still running into the same issues and I may have an idea why.
I create the session per request as and when it is needed but in my global.asax I am disposing of the session on Application_EndRequest. However I'm finding the Application_EndRequest is being fired more than once while I am in debug at the end of loading a page. I thought that the event is only suppose to fire once at the very end of the request but if it isn't and some other items are trying to use the Session (which is what the error is complaining about) for whatever weird reason that could be my problem and the Session is still thread safe it is just being disposed of to early.
Anyone got any ideas? I did a google and saw that the VS development server does cause issues like that but I am running it through IIS.