Release 10.1A: OpenEdge Development:
ProDataSets

> ## Building the client side change handler

> The first of these procedures, called `clientChanges.p`, runs on the client side of the application. (As with earlier examples, these simplified procedures do not actually use the AppServer, but can very easily be extended to do so.) This can be run from a client procedure such as the `BtnSave` trigger in the `Order` update window, and later you’ll do that.

> So, let’s create procedure `clientChanges.p` based on code from the `CHOOSE` trigger for `BtnSave` in `dsOrderWinUpd.w`.

> `ClientChanges.p` takes the ProDataSet handle as input, along with the supporting entity procedure handle. As we noted, this procedure handle parameter would be unnecessary if there were a single service procedure on the server to handle all updates. It returns any status messages as `OUTPUT`, as shown:

>     /* clientChanges.p -- client side of generic commitChanges support */
>     DEFINE INPUT  PARAMETER phDataSet     AS HANDLE.
>     DEFINE INPUT  PARAMETER phSupportProc AS HANDLE.
>     DEFINE OUTPUT PARAMETER pcStatus      AS CHARACTER.

> It defines variables for the handles of the change ProDataSet, query, buffer, and a buffer counter:

>     DEFINE VARIABLE hDSChanges AS HANDLE     NO-UNDO.
>     DEFINE VARIABLE hQuery     AS HANDLE     NO-UNDO.
>     DEFINE VARIABLE hBuffer    AS HANDLE     NO-UNDO.
>     DEFINE VARIABLE iBuffer    AS INTEGER    NO-UNDO.

> It creates a dynamic ProDataSet, makes it like the `INPUT` ProDataSet, and extracts changes from the input ProDataSet:

>     CREATE DATASET hDSChanges.
>     hDSChanges:CREATE-LIKE(phDataSet).
>     hDSChanges:GET-CHANGES(phDataSet).

> It then runs this generic `saveChanges` procedure in the support procedure handle, passing the change ProDataSet as `INPUT`-`OUTPUT`. This is done `BY-REFERENCE` so that in the case where this procedure and the supporting entity procedure are in the same session, the change ProDataSet does not need to be copied:

>     RUN saveChanges IN phSupportProc
>           (INPUT-OUTPUT DATASET-HANDLE hDSChanges BY-REFERENCE).

> If any errors were logged, it places them into the status parameter for return to the caller, as shown:

>     /* Check the ERROR status that might have been returned. */
>     IF hDSChanges:ERROR THEN
>        DO iBuffer = 1 TO phDataSet:NUM-BUFFERS:
>            CREATE QUERY hQuery.
>            hBuffer = hDSChanges:GET-BUFFER-HANDLE(iBuffer).
>            hQuery:ADD-BUFFER(hBuffer).
>            hQuery:QUERY-PREPARE("FOR EACH " + hBuffer:NAME).
>            hQuery:QUERY-OPEN().
>            hQuery:GET-FIRST().
>            DO WHILE NOT hQuery:QUERY-OFF-END:
>                IF hBuffer:ERROR THEN
>                    pcStatus = pcStatus + hBuffer:ERROR-STRING + CHR(10).
>                hQuery:GET-NEXT().
>            END.
>            hQuery:QUERY-CLOSE().
>            DELETE OBJECT hQuery.
>     END.

> And finally, it merges the final change records back into the ProDataSet passed in, deletes the dynamic change ProDataSet, and does a synchronize on behalf of the user interface to make sure it redisplays any parts of the ProDataSet that are on the screen:

>     hDSChanges:MERGE-CHANGES(phDataSet).
>     DELETE OBJECT hDSChanges.

>     phDataSet:GET-BUFFER-HANDLE(1):SYNCHRONIZE().

> It’s worth noting here that you need to decide when to use `MERGE-CHANGES` in your own applications. An additional parameter to `clientChanges.p` could provide some alternatives, or the generic procedure could leave the merge up to the caller entirely. If there were any errors, you might not want to do a `MERGE-CHANGES` because this rejects any change that has been marked with the `ERROR` or `REJECTED` attribute on the record, which restores the original record values. This overwrites whatever changes the user has made. Typically, you are more likely to want to leave the changes in the user interface alone, point them out to the user using the Status return messages, and give the user the opportunity to correct the errors without having to re-enter all changes. In this case, you should run `MERGE-CHANGES` only when the updates all succeeded. This is entirely up to you. In some cases the `SYNCHRONIZE` method might also better be left up to the caller.

> So now you have a general client-side change handler that you can call from any procedure that has accumulated changes in a ProDataSet. Now, move on to the server side of the update.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095