Progress OpenEdge 如何防止某人更新记录

Progress OpenEdge how to prevent someone from updating a record

我需要一种替代方法来防止某人访问特定代码段。

我会解释场景。

有两个程序。

在第一个程序中,最终用户创建形式发票。当 he/she 然后查看发票上的详细信息。该代码显示了 EXCLUSIVE-LOCK 中主要 table 记录的详细信息。这是为了防止其他最终用户在第一个用户忙于查看详细信息时更改任何内容。所以即使形式发票完成后也不能再更改。主 table 的记录仍处于独占锁定状态。这是错误的,但它可以防止其他用户在第一个用户仍在忙于更新它时弄乱它。但是,在该程序中工作的人员将程序留在详细信息视图中。他们不出门。

问题出在第二个程序用于发送形式发票上的项目时。它使用相同的主 table 记录。因此不能做任何事情,因为第一个程序仍然在独占锁中。

我的问题是...

如何防止用户在第一个程序中更改数据,就好像主 table 的记录处于排他锁状态,但实际上没有处于排他锁状态?在多个会话中...

很可能,您的事务范围是错误的。我将继续并假设您正在尝试在发票程序仍处于打开状态的情况下进行派送。那么你不能,因为记录仍然被锁定。很可能你的整个程序是一个事务,只要屏幕是 运行,记录就会保持锁定状态。尝试重新访问您的更新,将您真正的更新操作包含在 DO TRANSACTION 块中,将一些 MESSAGE TRANSACTION 语句放在不同的地方并查看结果。这将帮助您找到导致 Progress "believe" 记录仍然需要锁定的点。

我假设您没有使用应用服务器,因为在那种情况下这种行为很可能不会成为问题。

一种解决方案可能是更改为 "optimistic locking" 方法。这意味着您从 "NO-LOCK" 开始,一旦您需要更改记录,您就将锁升级为 EXCLUSIVE-LOCK。这种方法可行,但您需要确保该记录仍然存在并且未被其他用户更改。

根据您的发票实际更改的频率,这可能是(也可能不是)解决方案。如果发生意外 "once in a while" 这可能是一个可行的解决方案。如果它经常发生(每天左右),您需要做其他事情。

乐观方法的基本伪代码:

FIND FIRST record WHERE somethingsomething NO-LOCK.

/* Here goes code for displaying the record */
/* .... */

/* Here's the updates */
IF userWantsToSave THEN DO:
    FIND CURRENT record EXCLUSIVE-LOCK NO-ERROR NO-WAIT.
    IF AVAILABLE record THEN DO:
        IF CURRENT-CHANGED record THEN DO:
            MESSAGE "Changed!" VIEW-AS ALERT-BOX ERROR.
            /* Your code goes here */
        END.
        ELSE DO:
            /* Your code for updating goes here */

            MESSAGE "Success!" VIEW-AS ALERT-BOX INFORMATION.
        END.
    END.    
    ELSE IF NOT AVAILABLE record THEN DO:
        IF LOCKED record THEN DO:
            MESSAGE "Locked!" VIEW-AS ALERT-BOX ERROR.
            /* Your code goes here */
        END.
        ELSE DO:
            MESSAGE "Deleted!" VIEW-AS ALERT-BOX ERROR.
            /* Your code goes here */
        END.
    END. 
END.

Here's an example from the knowledgebase that goes more into depth with this.

这可能是一个更好的评论,但我没有足够的声誉点数来发表评论。对不起。

一些注意事项:

  1. 乐观锁定——如果它对你的情况可行——几乎肯定是最好的解决方案。

  2. 如果您要将 isLocked 字段添加到 table,您可能需要几个其他字段:

    • Date/Time 记录被锁定——或者过期时间戳
    • LockHolder -- 所以你知道你是否拥有它。
  3. 过期可以是自动的(与 cron 扫描一样),也可以忽略,除非其他人想要记录。设置锁的程序也必须足够聪明,可以检查它是否仍然持有它。变得复杂了。

  4. 有时不方便对 table 进行架构更改,或者需要更改的 table 太多。在这些情况下,您可以将这些字段添加到单独的 LockIt table。一个 table 可以为所有其他 table 处理这些锁。

旁白:
我们还将 LockIt table 用于另一个目的:确保一次只能 运行 给定程序的一个副本。 (通常这是用于 cron 作业或批处理守护进程。)该程序独占锁定 LockIt table 中的特定记录(但不启动事务!),并且只要程序是,它就会持有该锁定运行宁。