私はしばらくの間 NHibernate を使用してきましたが、2 つのページを同時に (またはできる限り近くで) 要求しようとすると、エラーが発生することがあります。したがって、セッション管理がスレッドセーフではないためだと思いました。
私のクラスだと思ったので、このブログ投稿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 が複数回発生していることがわかります。イベントはリクエストの最後に一度だけ発生すると思われますが、そうではなく、他のいくつかのアイテムがセッションを使用しようとしている場合 (これがエラーの原因です)、何らかの奇妙な理由で発生する可能性があります私の問題であり、セッションはまだスレッドセーフであり、早期に破棄されています。
誰でもアイデアはありますか?Google を実行したところ、VS 開発サーバーがそのような問題を引き起こしていることがわかりましたが、IIS を介して実行しています。