1

複数のプロセスの後に Rollback() または commit() 関数を使用したい。

エラーはありませんが、DB を更新するために commit() しません。

ここに私のコード例があります、

public void startTransaction(){
    using(Ads_A_Connection = new AdsConnection(Ads_A_connection_string))
    using(Ads_B_Connection = new AdsConnection(Ads_B_connection_string))
    {
        Ads_A_Connection.Open();
        Ads_B_Connection.Open();

        AdsTransaction aTxn = Ads_A_Connection.BeginTransaction();
        AdsTransaction bTxn = Ads_B_Connection.BeginTransaction();

        try{
            string aResult = this.process1(Ads_A_Connection);       
            this.process2(Ads_B_Connection, aResult);       
            this.process3(Ads_A_Connection. Ads_B_Connection);

            aTxn.Commit();
            bTxn.Commit();
            // there is no error, but it couldn't commit.
        }catch(Exception e){
            aTxn.Rollback();
            bTxn.Rollback();
        }
    }
}

public string process1(conn){
    // Insert data
    return result;
}

public void process2(conn. aResult){
    // update
}

public void process3(aConn, bConn){
    // delete
    // update
}

スコープを使用していないためだと思います。すべてのコードを startTransaction() メソッドに入れようとしたため、機能します。でも見た目が汚すぎる。

複数の (METHOD) プロセスの後に rollback() または commit() を使用するにはどうすればよいですか?

どなたかご存知の方アドバイスお願いします。

ありがとう!

[編集]

接続前に TransactionScope を追加するだけで、

using (TransactionScope scope = new TransactionScope())
{
   using(Ads_A_Connection = new AdsConnection(Ads_A_connection_string))
   using(Ads_B_Connection = new AdsConnection(Ads_B_connection_string))
   {
     .
     .

しかし、エラーが発生し、「エラー 5047: トランザクション コマンドが有効なシーケンスではありませんでした」と表示されます。

もう少しヒントが必要です:)

4

2 に答える 2

2

Etch が言及したことを拡張するために、接続でトランザクションを手動で管理する際のいくつかの問題があります。

  • メソッドの周りにSQL接続を渡す必要があります
  • 終了時に手動でコミットまたはロールバックすることを覚えておく必要がある
  • トランザクションで管理する接続が複数ある場合は、DTC または XA を実際に使用して、トランザクションを分散 / 2 フェーズ トランザクションに登録する必要があります。

TransactionScopesはAdvantage データベース サーバーでサポートされていますが、 MSDTC サービスを有効にし、場合によっては XA 準拠も有効にする必要があります。

利点 .NET クライアントにはある種の接続プール メカニズムがあると想定していることに注意してください。これにより、接続を取得するコストが非常に軽量になります。

最終的に、これは、コードを次のようなものにリファクタリングできることを意味します。これは保守が容易です。

private void Method1()
{
    using(Ads_A_Connection = new AdsConnection(Ads_A_connection_string))
    {
        Ads_A_Connection.Open();
        string aResult = this.process1(Ads_A_Connection);       
    } // Can logically 'close' the connection here, although it is actually now held by the transaction manager
}

private void Method2()
{
    using(Ads_B_Connection = new AdsConnection(Ads_B_connection_string))
    {
        Ads_B_Connection.Open();
        this.process2(Ads_B_Connection, aResult);       
    } // Can logically 'close' the connection here, although it is actually now held by the transaction manager
}


public void MyServiceWhichNeedToBeTransactional(){
    using(TransactionScope ts = new TransactionScope()) { // NB : Watch isolation here. Recommend change to READ_COMMITTED
        try{
           Method1();
           Method2();
           ts.Complete();
        }
        catch(Exception e){
          // Do Logging etc. No need to rollback, as this is done by default if Complete() not called
        }
    }
}
于 2012-08-14T14:29:23.327 に答える
1

TransactionScopeはあなたの友達です!

TransactionScope

于 2012-08-14T13:54:38.237 に答える