2017-11-26 7 views
0

次のコードがあります(説明のために簡略化してあります)。 proc1、proc2、およびproc3の異なるDBテーブルにレコードを作成しています。私が達成しようとしているのは、(たとえDBレコードを既に作成した後でも)いつでもテンポラリテーブルをループしている間にエラーが発生した場合は、すべてをロールバックしてレコードを作成しないことです。 proc1、proc2、proc3に問題がなければエラーをキャッチしますが、エラーをメイン処理ブロックに渡す方法を理解することができず、すべてを戻してロールバックします。言い換えれば、すでに作成されたレコードがDBに残るように、メッセージ( 'error @ main trans block')がポップアップすることはありません。実際、何もロールバックされません。処理ブロック外の手順のエラーをキャッチ

DO TRANSACTION ON ERROR UNDO, THROW: 

    FOR EACH tt1: 

     RUN proc1. 

     FOR EACH tt2 WHERE tt2.field1 EQ tt1.field1: 

      RUN proc2. 

      FOR EACH tt3 WHERE tt3.field2 EQ tt2.field2: 

       RUN proc3. 

      END. 

     END. 

    END. 

    CATCH e AS PROGRESS.Lang.AppERROR: 

     MESSAGE 'error @ main trans block' 
      VIEW-AS ALERT-BOX INFO BUTTONS OK. 

    END CATCH. 

END. 

PROCEDURE proc1. 
    DO TRANSACTION ON ERROR UNDO, THROW: 

     /* creating some DB records */ 

     CATCH e AS PROGRESS.Lang.ERROR: 

      RETURN ERROR 'Proc1 ' + e:getmessage(1). 

     END CATCH. 

    END. 

END PROCEDURE. 

PROCEDURE proc2. 
    DO TRANSACTION ON ERROR UNDO, THROW: 

     /* creating some DB records */ 

     CATCH e AS PROGRESS.Lang.ERROR: 

      RETURN ERROR 'Proc2 ' + e:getmessage(1). 

     END CATCH. 

    END. 

END PROCEDURE. 

PROCEDURE proc3. 
    DO TRANSACTION ON ERROR UNDO, THROW: 

     /* creating some DB records */ 

     CATCH e AS PROGRESS.Lang.ERROR: 

      RETURN ERROR 'Proc3 ' + e:getmessage(1). 

     END CATCH. 

    END. 

END PROCEDURE. 

TIA

答えて

1

潜在的な問題がいくつかあります。

まず、テンポラリテーブルtt1とtt2をNO-UNDOフラグなしで定義する必要があります。

第2に、FOR EACHブロックは、デフォルトのエラー処理の動作(ON ERROR UNDO, NEXT.)を使用しています。したがって、FOR EACHブロック内で発生したエラーは、トランザクション全体ではなく、現在の繰り返しを元に戻します。

私はプログラムの先頭に

BLOCK-LEVEL ON ERROR UNDO, THROW . 

を追加することをお勧めします。すべてのFOR EACHブロック上ON ERROR UNDO, THROWオプションと組み合わせて、または少なくとも

ROUTINE-LEVEL ON ERROR UNDO, THROW . 

BLOCK-LEVELエラー処理オプションはOpenEdge 11.3(またはそれ以降)から利用可能です。

+0

こんにちはマイク、あなたの提案に感謝します。それはうまくいったが、私はこの権利を説明したとは思わない。私はBLOCK-LEVELをプロシージャの先頭に追加し、プロシージャ全体が元に戻されます。しかし、私は、特定のブロックと、このブロックが元に戻すすべての内部プロシージャだけを必要とします。私は別のファイルでこのロジックを分離することを避けたいと思います。特定のコードブロックと、このコードの内側から呼び出されているすべてのコードだけを元に戻す方法はありますか? – Tony

+0

これはブロックラベルを使用できる理由です。 (反復)ブロックの前に、my-label:FOR EACH ....のような操作をしてから、UNDO、LEAVE my-labelを実行します。 –

+0

こんにちはマイク、私は何か(たとえば、永続的なDBレコードを作成する)プロシージャを呼び出す場合、このアプローチは、反復ブロック内から動作しますか?たとえば..... createBlock:各....エラーではcreateBlockを元に戻し、createBlockから離れる:createProcを実行します。終わり。 createProc。 ..... permanentDBTableを作成します。終了手順。すでに10のDBレコードを作成していて、FOR EACHの11回目の反復で、私はcreateProcにエラーがあります。それ以前に作成された10個のレコードのすべてをロールバック(未作成)しますか? – Tony

関連する問題