2009-10-26 5 views
6

Webアプリケーション内でAutofacを使用してNHibernateトランザクションを管理する最良の方法は何ですか?ASP.NET(MVC)内のAutofacを使用するNHibernate:ITransaction

セッションへの私のアプローチはITransactionについては

builder.Register(c => c.Resolve<ISessionFactory>().OpenSession()) 
     .ContainerScoped(); 

ですが、私はGoogle Codeの上found an exampleを持っていますが、ロールバックするかどうかを決定する際には、HttpContext.Current.Errorに依存しています。

もっと良い解決策はありますか?そして、どの範囲のNHibernateトランザクションにありますか?

答えて

4

を自分自身を管理し、私はしばらく前の投稿:

修正

http://groups.google.com/group/autofac/browse_thread/thread/f10badba5fe0d546/e64f2e757df94e61?lnk=gst&q=transaction#e64f2e757df94e61

、インターセプタは能力と[トランザクション]ログインしているように属性をすることができますクラスでも使用できます。

+1

私は解決策が好きです。しかし、別の問題は、どのような方法で[トランザクション]を適用すべきかということですか?このhttp://nhprof.com/Learn/Alert?name=DoNotUseImplicitTransactionsによると、セッションがある場合は常にトランザクションが必要なようですが、このソリューションでは、セッションが使用されているどこでも[トランザクション]を手動で追加する必要があります。 –

+0

変更されたバージョンを確認してください。あなたはおそらくそこからそれを変更する方法を知っているでしょう。 また、[Transaction]属性をスキップして、常にトランザクションを開始することもできます。それはあなたの選択です。時々私は別のトランザクションで2つのことをする必要があったので、私は属性が必要でした。 私はこのようにしました: //トランザクション属性なし public virtual void CallThis() { Trans1(); //コミット Trans2(); //コミット } [トランザクション] パブリック仮想空TRANS1(){} [トランザクション] パブリック仮想空TRANS2(){} – dmonlord

+0

次の2つのトランザクションのためのユースケースを説明してもらえますか?これは重要なことです。なぜなら、同様のユースケースに遭遇する可能性がある場合は、問題を別の方法で見ていきます。 –

-1

私は通常..トランザクションに

public ActionResult Edit(Question q){ 
try { 
using (var t = repo.BeginTransaction()){ 
    repo.Save(q); 
    t.Commit(); 
    return View(); 
} 
catch (Exception e){ 
    ... 
} 
} 
+1

これは最も簡単な解決策ですが、ちょっと面倒で、全体の方法にインデントを追加します。 –

+0

確かに、2行と1字下げですが、ある日、あなたは同じ要求で2つのトランザクションを行う必要があることを認識しています。 –

+1

ほとんどの人はCtrl + C/Ctrl + Vを何度も押したくない – Paco

4
[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; 
    } 
} 

Iは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; 
     } 

    } 

私は(AB)これを管理するためにautofacで決定論的処分のものを使用していて、よく私は一種のそれを好みます。

もう1つは、基本的にはASPNet環境のみをターゲットにしており、取引がWebリクエストに結びついているという意識的な決定を下したことです。したがって、Web要求パターンごとのトランザクション。

私はのIHttpModuleで処理コードこのエラーを行うことができるのので:

void context_Error(object sender, System.EventArgs e) 
    { 
     _containerProvider.RequestContainer.Resolve<IUnitOfWork>().Rollback(); 
    } 

私はあまりにも密接にNHibernate.Burrowを見て撮影していないが、私はほとんどありませんが、何かがあると確信していますこれの。

+0

あなたの考えは、Autofacの考え方に非常によく似ています。私はそれが大好きです。残念ながら、私は2つの答えを受け入れることができないので、私は最初のものを選択します(また、dmonlordは評判があまりありません)。 –

関連する問題