2009-03-24 7 views
7

ビジネス計算を実行し、データベースにレコードを作成する必要がある状況があります(私はかなり標準的です)。ある時点で何かがうまくいかない場合は、データベースからすべてをロールバックする必要があります。うーん、私はある種の取引が必要です。私の質問は、トランザクションサポートを実装する場所です。ここに私の例がありますビジネスプロセスとリポジトリパターンとのトランザクションの使用

//BillingServices - This is my billing service layer. called from the UI 
public Result GenerateBill(BillData obj) 
{ 
    //Validate BillData 

    //Create a receivable line item in the receivables ledger 
    BillingRepository.Save(receivableItem); 

    //Update account record to reflect new billing information 
    BillingRepository.Save(accountRecord); 

    //...do a some other stuff 
    BillingRepository.Save(moreStuffInTheDatabase); 
} 

データベースの更新が失敗した場合は、他のものをロールバックして脱出する必要があります。私はちょうど私が

Connection.BeginTransactionを(呼び出すことができますここで、私のリポジトリを介した接続オブジェクト)

を公開したり、私はちょうどサービス層に検証し、ちょうどすべて保存し、リポジトリに1つのメソッドを呼び出して行うのですかオブジェクトとトランザクションを処理する?これは私にとっては正しそうに見えません。データレイヤーに多くのビジネスロジックを置く必要があるようです。

正しいアプローチは何ですか?リポジトリを広げる必要がある場合(またはそれが悪い設計の場合)はどうでしょうか?

+1

+1、良い質問があります。 –

+0

うまくいけばよい答えを得るでしょう=)。実際には、この時点での答えはいいです – Micah

答えて

5

ここでは.NETを使用していると仮定しています。つまり、using statementのコードセクション全体をTransactionScopeインスタンスでラップするだけで、トランザクションのセマンティクスが処理されます。あなたは、単に最後にComplete methodを呼び出す必要があり:

//BillingServices - This is my billing service layer. called from the UI 
public Result GenerateBill(BillData obj) 
{ 
    // Create the transaction scope, this defaults to Required. 
    using (TransactionScope txScope = new TransactionScope()) 
    { 
      //Validate BillData 

      //Create a receivable line item in the receivables ledger 
      BillingRepository.Save(receivableItem); 

      //Update account record to reflect new billing information 
      BillingRepository.Save(accountRecord); 

      //...do a some other stuff 
      BillingRepository.Save(moreStuffInTheDatabase); 

      // Commit the transaction. 
      txScope.Complete(); 
    } 
} 

例外が発生した場合、これはコードブロックが終了したときCompleteを呼び出していないという効果があります。 TransactionScopeIDisposable interfaceDispose methodは、usingステートメントの有効範囲が終了すると呼び出されます。

Disposeコールでは、トランザクションが完了したかどうかを確認します(この状態は、Completeが成功したときに設定されます)。その状態が設定されていない場合は、ロールバックを実行します。

これを他のTransactionScopeインスタンス(同一スレッド上のコールスタックの深い部分)にネストすると、複数のリポジトリ間でより大きなトランザクションを作成できます。

+0

私はかなり標準をしているのですが、これは最も一般的な解決策ですか? – Micah

+0

@Micah:.NETを使用していると仮定します。はい、これは、複数のメソッド/オブジェクト/トランザクションリポジトリにまたがるトランザクションを展開する場合に推奨される方法です。 – casperOne

+0

恐ろしい!どうもありがとう! – Micah

関連する問題