はい。これは、Castle Windsor に ISession を解決するように依頼する方法に関連する問題ですが、コードを 5 回ほど読み直しましたが、何が問題なのかまだわかりません。
以下は、私が登録した最後の 2 つのコンポーネントを除いて、かなり標準的な NHibernate 機能です。
public class NHibernateFacility : AbstractFacility
{
protected override void Init()
{
var config = new Configuration().Configure();
Kernel.Register(
Component.For<ISessionFactory>()
.UsingFactoryMethod((kernel, context) => config.BuildSessionFactory()),
Component.For<ISession>()
.UsingFactoryMethod((kernel, context) => kernel.Resolve<ISessionFactory>().OpenSession())
.LifestylePerWebRequest(),
Component.For<IStatelessSession>()
.UsingFactoryMethod((kernel, context) => kernel.Resolve<ISessionFactory>().OpenStatelessSession())
.LifestylePerWebRequest(),
Component.For<StatefulSessionWrapper>().LifestylePerWebRequest(),
Component.For<StatelessSessionWrapper>().LifestylePerWebRequest()
);
}
}
StatefulSessionWrapper/StatelessSessionWrapper は、次のような ISession/IStateless セッションの ... ラッパーとして機能します。
public class StatefulSessionWrapper : ISessionWrapper
{
public StatefulSessionWrapper(ISession session)
{
this.Session = session;
}
private readonly ISession Session;
#region ISessionWrapper Members
public ITransaction BeginTransaction()
{
return Session.BeginTransaction();
}
public ITransaction BeginTransaction(IsolationLevel isolationLevel)
{
return Session.BeginTransaction(isolationLevel);
}
public ITransaction Transaction { get { return Session.Transaction; } }
public bool IsConnected
{
get { return Session.IsConnected; }
}
public bool IsOpen
{
get { return Session.IsOpen; }
}
#endregion
}
このようにして、NHibernate セッションのトランザクション部分のみを処理する単一のアクション フィルターを使用できます。
public class NHibernateActionFilter<T> : Castle.MonoRail.Framework.IFilter where T:ISessionWrapper
{
private readonly T NHibernateSession;
public NHibernateActionFilter(T session)
{
if (session != null)
NHibernateSession = session;
else
throw new NullReferenceException("Session is null");
}
#region IFilter Members
public bool Perform(ExecuteWhen exec, IEngineContext context, IController controller, IControllerContext controllerContext)
{
if (exec == ExecuteWhen.BeforeAction)
{
NHibernateSession.BeginTransaction();
return true;
}
if (exec == ExecuteWhen.AfterAction)
{
if (NHibernateSession.Transaction == null || !NHibernateSession.Transaction.IsActive)
return false;
if (context.LastException != null)
{
NHibernateSession.Transaction.Rollback();
return false;
}
else
{
NHibernateSession.Transaction.Commit();
return true;
}
}
return false;
}
#endregion
}
そして、次のように単純に使用します。
[Filter(ExecuteWhen.Always, typeof(NHibernateActionFilter<StatefulSessionWrapper>), ExecutionOrder = 1)]
[Filter(ExecuteWhen.BeforeAction, typeof(AuthenticationFilter), ExecutionOrder = 2)]
[Layout("Default"), Rescue("Default")]
public abstract class NHibernateController : SmartDispatcherController
{
public NHibernateController(ISession session)
{
this.NHibernateSession = session;
}
protected readonly ISession NHibernateSession;
..................
唯一の問題?
レスキューページです。以下の例外の詳細を参照してください
ObjectDisposedException
メッセージ: セッションが終了しました! オブジェクト名: 'ISession'。
StackTrace: p:\nhibernate-core\src\NHibernate\Impl\AbstractSessionImpl.cs: 207 行目の NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() p:\nhibernate-core\ の NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus() src\NHibernate\Impl\AbstractSessionImpl.cs: p:\nhibernate-core\src\NHibernate\Impl\SessionImpl.cs の NHibernate.Impl.SessionImpl.BeginTransaction() の行 199: ADAutoTotal.Monorail.StatefulSessionWrapper.BeginTransaction の行 1456 () in C:\Dropbox\Projects\ADAutoTotal\ADAutoTotal.Monorail\StatefulSessionWrapper.cs:line 23 at ADAutoTotal.Monorail.NHibernateActionFilter`1.Perform(ExecuteWhen exec, IEngineContext context, IController controller, IControllerContext controllerContext) in C:\Dropbox \Projects\ADAutoTotal\ADAutoTotal.Monorail\NHibernateActionFilter.cs:C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac\MR2\src\Castle.MonoRail.Framework の Castle.MonoRail.Framework.Controller.ProcessFilter(ExecuteWhen when, FilterDescriptor desc) の 31 行目\Controller.cs: C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac\MR2\src\ の Castle.MonoRail.Framework.Controller.ProcessFilters(IExecutableAction action, ExecuteWhen) の 2099 行目Castle.MonoRail.Framework\Controller.cs: C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac の Castle.MonoRail.Framework.Controller.RunBeforeActionFilters(IExecutableAction action, Boolean& cancel) の行 2054 \MR2\src\Castle.MonoRail.Framework\Controller.cs:Castle.MonoRail.Framework.Controller の 1953 行。C:\Dropbox\Projects\Monorail\castleproject-MonoRail-98c93ac\castleproject-MonoRail-98c93ac\MR2\src\Castle.MonoRail.Framework\Controller.cs:line 1622 の RunActionAndRenderView()
したがって、NHibernateActionFilter がクローズド セッションを取得することは明らかです。しかし、私によれば、そうすべきではありません。半分。