ASP.NET(MVC)内でAutofacを使用するNHibernate:ITransaction
-
06-07-2019 - |
質問
Webアプリケーション内でAutofacを使用してNHibernateトランザクションを管理する最良の方法は何ですか?
セッションへの私のアプローチは
builder.Register(c => c.Resolve<ISessionFactory>().OpenSession())
.ContainerScoped();
ITransaction
には、 Google Codeで例が見つかりましたが、ロールバックするかどうかを決定する際に HttpContext.Current.Error
に依存しています。
より良い解決策はありますか?また、NHibernateトランザクションのスコープは 必要ですか?
解決
しばらく前に投稿しました:
インターセプターにロギング機能があり、[トランザクション]属性もクラスで使用できるように変更されました。
[global::System.AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TransactionAttribute : Attribute
{
}
public class ServicesInterceptor : Castle.Core.Interceptor.IInterceptor
{
private readonly ISession db;
private ITransaction transaction = null;
public ServicesInterceptor(ISession db)
{
this.db = db;
}
public void Intercept(IInvocation invocation)
{
ILog log = LogManager.GetLogger(string.Format("{0}.{1}", invocation.Method.DeclaringType.FullName, invocation.Method.Name));
bool isTransactional = IsTransactional(invocation.Method);
bool iAmTheFirst = false;
if (transaction == null && isTransactional)
{
transaction = db.BeginTransaction();
iAmTheFirst = true;
}
try
{
invocation.Proceed();
if (iAmTheFirst)
{
iAmTheFirst = false;
transaction.Commit();
transaction = null;
}
}
catch (Exception ex)
{
if (iAmTheFirst)
{
iAmTheFirst = false;
transaction.Rollback();
db.Clear();
transaction = null;
}
log.Error(ex);
throw ex;
}
}
private bool IsTransactional(MethodInfo mi)
{
var atrClass = mi.DeclaringType.GetCustomAttributes(false);
foreach (var a in atrClass)
if (a is TransactionAttribute)
return true;
var atrMethod = mi.GetCustomAttributes(false);
foreach (var a in atrMethod)
if (a is TransactionAttribute)
return true;
return false;
}
}
他のヒント
autofacを使用するときは、同じコンテナスコープメソッドを使用しますが、同じセッションをリポジトリ/ DAOオブジェクトに渡す代わりに、コンテナスコープのUnitOfWorkを渡します。作業ユニットのコンストラクタにはこれがあります。
private readonly ISession _session;
private ITransaction _transaction;
public UnitOfWork(ISession session)
{
_session = session;
_transaction = session.BeginTransaction();
}
そして破棄は:
public void Dispose()
{
try
{
if (_transaction != null &&
!_transaction.WasCommitted &&
!_transaction.WasRolledBack)
_transaction.Commit();
_transaction = null;
}
catch (Exception)
{
Rollback();
throw;
}
}
私はこれを管理するためにautofacで決定論的な廃棄物を使用しています(ab)。
もう1つは、基本的にASPNet環境のみを対象としており、トランザクションがWeb要求に関連付けられているという意識的な決定を行ったことです。したがって、Webリクエストパターンごとのトランザクション。
そのため、IHttpModuleでこのエラー処理コードを実行できます。
void context_Error(object sender, System.EventArgs e)
{
_containerProvider.RequestContainer.Resolve<IUnitOfWork>().Rollback();
}
私はNHibernate.Burrowをあまり詳しく調べていませんが、これのほとんどを行う何かがあると確信しています。
通常、トランザクションは自分で管理します。.
public ActionResult Edit(Question q){
try {
using (var t = repo.BeginTransaction()){
repo.Save(q);
t.Commit();
return View();
}
catch (Exception e){
...
}
}
所属していません StackOverflow