【问题标题】:Catching errors from procedures outside of processing block从处理块之外的过程中捕获错误
【发布时间】:2017-11-26 15:10:00
【问题描述】:

我有以下代码(为了便于说明,已简化)。我在 proc1、proc2 和 proc3 的不同数据库表中创建记录。我想要实现的是......如果我在任何时候循环遍历临时表时遇到错误(即使在我已经创建了一堆数据库记录之后),我想回滚所有内容,因此不会创建任何记录。如果 proc1、proc2 和 proc3 没有问题,它会捕获错误,但我无法弄清楚如何将这些错误传递给主处理块,以便它理解并回滚所有内容。换句话说,消息('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

【问题讨论】:

    标签: openedge progress-4gl


    【解决方案1】:

    有几个潜在的问题。

    首先,您的临时表 tt1 和 tt2 需要在没有 NO-UNDO 标志的情况下定义。

    其次,FOR EACH 块使用它们的默认错误处理行为,即ON ERROR UNDO, NEXT.,因此在 FOR EACH 块中引发的错误将导致当前迭代被撤消,而不是整个事务。

    我建议添加

    BLOCK-LEVEL ON ERROR UNDO, THROW . 
    

    到程序的顶部。或者至少

    ROUTINE-LEVEL ON ERROR UNDO, THROW . 
    

    结合所有FOR EACH 块上的ON ERROR UNDO, THROW 选项。

    BLOCK-LEVEL 错误处理选项自 OpenEdge 11.3(或更高版本)起可用。

    【讨论】:

    • 嗨,迈克,感谢您的建议。它有点奏效,但我认为我没有正确解释这一点。我在程序顶部添加了 BLOCK-LEVEL,现在整个程序都被撤消了。但是,我只需要一个特定的块和该块调用的所有内部过程。我想避免将此逻辑分隔在一个单独的文件中。肯定有一种方法可以撤消特定的代码块以及从该代码内部调用的所有代码?
    • 这就是块标签的用途。在(迭代)块之前,执行 my-label: FOR EACH .... 之类的操作,然后 UNDO,LEAVE my-label。
    • 嗨,迈克,如果我在迭代块中调用一个执行某些操作(例如,创建永久数据库记录)的过程,这种方法会起作用吗?例如..... createBlock: for each .... on error undo createBlock, leave createBlock: run createProc。结尾。创建过程。 .....创建永久数据库表。结束程序。如果我已经创建了 10 条数据库记录,并且在 FOR EACH 的第 11 次迭代中,我在 createProc 中出现错误,它会回滚(取消创建)之前创建的所有 10 条记录吗?
    • 如果你有一个外部事务块并且那个块是你撤销的那个块,那么是的
    • 嗨,迈克,我添加了块标签,效果很好。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    相关资源
    最近更新 更多