NHibernate 3 で新しいプロジェクトを開始しており、WebSessionContext で CurrentSessionContext API を使用して ISession オブジェクトを管理しようとしています。
以前のプロジェクトでは、私は常にそれを自分で管理していたので、ISession オブジェクトが必要になるたびに、それを作成して HttpContext.Items コレクションに格納していました。非常に簡単ですが、この新しいプロジェクトにはネイティブ ソリューション (CurrentSessionContext) を使用するのが最適なオプションのようです。
オブジェクトを管理したときに、遅延初期化を行うことができました。つまり、すべてのリクエストではなく、必要なときにのみセッションを開くことができました。これは、必要ない可能性があり、すべてを開くことでリソース/時間を浪費するためです。時間。
CurrentSessionContext API でそれを行う簡単な方法はありますか?
これを担当する HttpModule で使用しているコードは次のとおりです。
public class ContextualSessionModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
public void Dispose()
{
}
private static void context_BeginRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
BindSession(context);
}
private static void BindSession(HttpContext context)
{
// Create a new session (it's the beginning of the request)
var session = SessionBuilderFactory.CurrentSessionFactory.OpenSession();
// Tell NH session context to use it
CurrentSessionContext.Bind(session);
}
private static void context_EndRequest(object sender, EventArgs e)
{
var application = (HttpApplication)sender;
var context = application.Context;
UnbindSession(context);
}
private static void UnbindSession(HttpContext context)
{
// Get the default NH session factory
var factory = SessionBuilderFactory.CurrentSessionFactory;
// Give it to NH so it can pull the right session
var session = CurrentSessionContext.Unbind(factory);
if (session == null) return;
session.Flush();
session.Close();
}
}
編集
Diego はほぼ完璧にやり遂げましたが、私はこれについてもう少し考え、私がそのコントロールを自分で実装した主な理由を思い出しました: トランザクションです。
私はオニオン アーキテクチャの専門家なので、ドメイン オブジェクト (いつトランザクションを開始するかを知っているオブジェクト) はインフラストラクチャにアクセスできないため、トランザクションを開始できません。
これを解決するために、遅延初期化を使用し、セッションを開くときに常にトランザクションを開始します。コミットは、リクエストが終了し、例外がキャッチされなかったときに発生します。これに加えて、クエリを実行する場合でも、常にトランザクションを使用するという Ayende のアドバイスがあります。何かご意見は?