ASP.NETMVCアプリケーションのStructureMapネストされたコンテナーを使用したNHibernateセッションおよびトランザクション管理に関する経験を共有していただきたいと思います。ActionFilterAttribute
誰かがトランザクション分離レベルでパラメーター化され、、をオーバーライドしてNHibernateトランザクションを開始およびコミット/ロールバックするを作成しようとしたことがOnActionExecuting
ありOnActionExecuted
ますOnResultExecuted
か。私はあなたの専門知識を本当に感謝します。
私は、Building a Better MVC Dependency Resolverを使用してDependencyResolverを構築し、ASP.NET MVC:FiltersでTransactionAttributeDependencyInjectionにISessionを注入しました。
また、次の実装でTransactionAttributeクラスを作成します。
public class TransactionAttribute : ActionFilterAttribute
{
public ISession Session { get; set; }
public bool Distributed { get; set; }
public IsolationLevel IsolationLevel
{
get { return _isolationLevel; }
set { _isolationLevel = value; }
}
private ITransaction _sessionTransaction;
private TransactionScope _transactionScope;
private IsolationLevel _isolationLevel = IsolationLevel.ReadCommitted;
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.IsChildAction)
return;
if (Session.Transaction == null || !Session.Transaction.IsActive)
{
if (Distributed)
_transactionScope = new TransactionScope(TransactionScopeOption.Required);
_sessionTransaction = Session.BeginTransaction(IsolationLevel);
}
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.IsChildAction)
return;
if (_sessionTransaction != null)
{
if (filterContext.Exception != null && !filterContext.ExceptionHandled)
{
try
{
_sessionTransaction.Rollback();
}
finally
{
if (_transactionScope != null)
_transactionScope.Dispose();
}
}
}
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
if (filterContext.IsChildAction)
return;
if (_sessionTransaction != null)
{
try
{
if (filterContext.Exception == null || filterContext.ExceptionHandled)
{
_sessionTransaction.Commit();
if (_transactionScope != null)
_transactionScope.Complete();
}
else
{
_sessionTransaction.Rollback();
}
}
finally
{
if (_transactionScope != null)
_transactionScope.Dispose();
}
}
}
}
規則を使用して、コントローラーのunqiueインスタンスを作成するようにします。
public class ControllerConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (type.IsClass && !type.IsAbstract && typeof(IController).IsAssignableFrom(type))
{
registry.For(type).LifecycleIs(InstanceScope.Unique).Add(type);
}
}
}
私が抱えている問題は、それが単純なケースで機能することです。ただし、より複雑なケースでは、すでに破棄されたオブジェクトへのアクセスに関するエラーメッセージを受け取ることがあります。また、ロギングを追加しましたが、Sessionプロパティにはすでに古いオブジェクトが割り当てられているため、TransactionAttributeオブジェクトインスタンスが頻繁に再利用されることに気付きました。
ASP.NET MVCアプリケーションでActionFilterAttributesのライフサイクルを制御して、NHibernateセッションと一緒にネストされたコンテナーを介して破棄できるかどうかも知りたいです。ActionFilterAttributeは完全にステートレスである必要があり、そのための適切な実装は何でしょうか。
さらに詳しい情報が必要な場合はお知らせください。