2017-11-26 21 views
0

다음 코드가 있습니다 (설명의 편의를 위해). proc1, proc2 및 proc3의 다른 DB 테이블에 레코드를 생성합니다. 내가 달성하고자하는 것은 ... DB 테이블 레코드를 이미 만든 후에도 임시 테이블을 반복하면서 오류가 발생하면 모든 레코드를 다시 롤백하여 레코드를 만들지 않기를 원합니다. proc1, proc2 및 proc3이 문제없이 catch되면 오류가 발생하지만 주 처리 블록에 오류를 전달하는 방법을 이해할 수 없으므로 오류를 이해하고 모든 오류를 롤백합니다. 즉, 이미 작성된 레코드가 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 플래그없이 정의해야합니다.

두 번째로 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. ..... create permanentDBTable. 엔드 절차. 이미 10 개의 DB 레코드를 만들고 FOR EUC의 11 번째 반복에서 createProc에 오류가 발생하면 이전에 생성 된 10 개의 레코드를 모두 롤백 (생성 취소) 할 예정입니까? – Tony