Maintaining transaction consistency between client and server
One disadvantage of using normal ABL transactions on the PAS for OpenEdge is that, because a normal ABL transaction completes and releases all locks before returning to the client, you may have to do extra work to ensure that the transaction completes as the client expects.
A typical scenario where this behavior might pose a problem is where the server returns data derived from a database to a client application. The client then modifies the data and returns it to the server with the intent that the changes to the data are to be applied to the database. Because database locks are not held across interactions with the server, the server cannot simply change the data in the database because the data might have already been changed by another user. Thus, transaction consistency in this situation cannot be easily maintained.
One approach to work around this problem to have the server keep a copy of the original data that is returned to the client application. In a server session, you can maintain a separate buffer or temp-table to hold a copy of the data. You must use the SERVER-CONNECTION-CONTEXT attribute of the SESSION system handle or a context database to maintain a copy of the data. For more information, see the sections on managing unbound session-managed connection context in Programming the Progress Application Server for OpenEdge.
When it is time to apply the updated data, the server session handling the request determines whether the database was changed by another user by comparing the original data to the data in the database. The following figure describes this approach.
Figure 6. Transaction data flow
The numbers in the previous figure correspond to the following explanation of transaction data flow:
1. The client application runs a remote persistent procedure on the server to request the data. The PAS for OpenEdge instance gets the data from the database and stores it in a temp-table (Orig).
2. As a result of the remote persistent procedure call, the server returns a copy of the Orig temp-table to the client application (Client).
3. The client application makes application-specific changes to its copy (Client~) that include creating, deleting, and modifying records.
4. The client application sends its modified copy (Client~) to the server by running an internal procedure of the persistent procedure instantiated in Step 1. The server stores its copy of the table in Client-Out.
5. Within a single transaction, the server compares the records that are in the Orig temp-table to the data in the database. If there are any differences, the server session knows that the data was changed by another user, aborts the transaction, and notifies the client application that the updates failed.
6. If the data has not been changed (within the same transaction as Step 5), the server then compares the Client-Out table to the Orig table. For each record within the Client-Out table that has been created, modified, or deleted, the server makes the same changes to the data within the database.
There are variations on the approach suggested in the previous figure that provide similar results, and exactly how you vary this scheme will depend on your particular application requirements. For example, in Step 5, even if the server finds a difference between the records in the Orig temp-table and the records in the database, it might not be necessary to abort the transaction. An alternative approach is to simply note which record has changed, find the corresponding record in the Client-Out temp-table returned to the server, and skip that when applying the changes in Step 6. Only you can decide what approach is appropriate for your application.
Note: You can greatly simplify this process by using an ABL dataset object (ProDataSet) to hold the temp-table or temp-tables involved in the transaction, with all of them defined using the BEFORE-TABLE option. This option provides before-image support in the ProDataSet. By exchanging this ProDataSet as an INPUT-OUTPUT parameter of the remote procedure, the server can apply and manage database changes using methods and events of the ProDataSet, and the client can also respond to any errors that are returned for each changed record on the server. For more information, see OpenEdge Development: ProDataSets.