Special support for change conflicts
- Last Updated: March 30, 2020
- 5 minute read
- OpenEdge
- Version 12.2
- Documentation
Because the ProDataSet with its independent FILL and save operations
necessarily relies on an optimistic locking strategy, you need to consider what behavior you
want in the event of a conflict with another change made since the ProDataSet was filled
from its Data-Source. The AVM supports a number of options to give you automated support for
almost any circumstance.
The first decision you need to make is whether a conflict with another change should be overwritten by the current ProDataSet's change, or rejected when the AVM detects a conflict.
In some cases, you might not care whether a record has been changed by another user since
it was read. Although this is certainly not typical or recommended, for some
non-transactional tables that contain fields that can safely be changed independently of one
another (possibly address information, for example), you might not want to reject a change
if the record has been changed elsewhere. There is a PREFER-DATASET logical
attribute for the Data-Source to support this option. The attribute is false by default. If
PREFER-DATASET is false for the table's Data-Source, then the AVM makes
the comparison between the before-table row in the database and the corresponding
Data-Source fields before applying the change. If there is any conflict, then the change is
rejected and the ERROR attribute is set. If PREFER-DATASET
is true, this check is not made. The ProDataSet row changes are written to the Data-Source
without regard to any other changes made to the same row. As noted previously, only the
database fields that are present in the ProDataSet temp-table, either implicitly or by being
mapped to a field with a different name, can be compared.
You also may want to apply changes and resolve conflicts on a field by field basis. This is
somewhat more expensive than either applying or rejecting all changes, but minimizes the
overwriting of either your changes or another user's changes when a conflict occurs. There
is a MERGE-BY-FIELD logical attribute on the Data-Source to specify this
preference. This attribute is true by default. It gives you the ability to define whether a
change is wholly rejected if there are any conflicting changes, even to different fields
than the ones the ProDataSet is changing.
If MERGE-BY-FIELD is false and if another user has changed a record, the
ProDataSet changes are either entirely accepted or entirely rejected, depending on the
setting of PREFER-DATASET. If MERGE-BY-FIELD is true, then
the AVM "blends" the two sets of changes where possible, if they are to different fields. If
it is true, then changes are applied field-by-field only for modified fields, and there is
no conflict unless the same field has been modified both by the current update and by
another transaction. A logical DATA-SOURCE-MODIFIED attribute on the
temp-table buffer is set to true if any field changes by another transaction are detected,
regardless of whether they result in a conflict and error or not. Note that it is somewhat
slower to have MERGE-BY-FIELD set to true, so it can be set to false to
improve performance where a field-by-field check is really not necessary, in addition to
cases where it is not wanted because of the application logic.
Here are the details of how changes are applied in the face of these attributes. In this
description, "current changes" refers to modifies and deletes that are part of a ProDataSet
the procedure is doing a SAVE-ROW-CHANGES on (the "current ProDataSet").
Obviously create operations do not need to check for conflicting field values. "Other
changes" refers to changes made to the fields in the same rows by another user or procedure
since the current ProDataSet was filled, which will be detectable by comparing the database
buffers with the before-tables in the current ProDataSet.
If MERGE-BY-FIELD is false, then these are the actions:
- If
PREFER-DATASETis true, then the modified or deleted row is updated or deleted without regard to whether there were other changes. In the case of a modify, all fields in the current ProDataSet row are copied to the database buffer, whether they were changed in the current ProDataSet or not. In the case of a delete, the database record is simply deleted. - If
PREFER-DATASETis false (the default), then the AVM compares the ProDataSet before-table with the database buffers. If there are any other changes, then the current change is rejected and the AVM sets theERRORattribute. If the action was a delete, the row is not deleted from the database or the current ProDataSet. The AVM also sets theDATA-SOURCE-MODIFIEDattribute on the row. It buffer-copies the entire database buffer back to the current ProDataSet's after-table row, to allow the changes to be seen back on the client.
If MERGE-BY-FIELD is true (the default), then rather than doing a
wholesale buffer-copy in one direction or the other, the AVM does a field-by-field compare
of the two buffers. In this case:
- This is the action if
PREFER-DATASETis true:- If the operation is a delete, then the database row is deleted without regard to whether there were other changes.
- Otherwise, for a Modify:
- If the field has not been changed in the current ProDataSet, then nothing is copied. This means that a change made by another user to a field that was not changed in the current ProDataSet will not be overwritten by the current change.
- If the field has been changed in the current ProDataSet, it is copied to the database field. There is no check of whether there were other changes.
- These are the actions if
PREFER-DATASETis false:- If the operation is a delete, and there are no other changes to the row, then the database record is deleted.
- If the operation is a delete, and there are other changes to the row, then
the delete fails, the AVM buffer-copies the entire database record into the ProDataSet
buffer, and sets the
ERRORandDATA-SOURCE-MODIFIEDattributes.
- Otherwise, for a Modify:
- If the field was changed in the current ProDataSet and not by other changes, then it is copied to the database.
- If the field was not changed in the current ProDataSet, and also not by other changes, then nothing is copied.
- If the field was changed in the current ProDataSet, and by other
changes, then the AVM checks whether the other changes are the same as the current
ProDataSet change. If this is the case, the AVM sets the
ERRORflag. If the changed values are different, the AVM buffer-copies that one field from the database record back into the ProDataSet buffer, and sets theERRORandDATA-SOURCE-MODIFIEDflags. The current ProDataSet changes are not applied to the database, but the field by field comparison continues so that only those fields changed by other changes overwrite the current ProDataSet changes. - If the field was not changed in the current ProDataSet, but was changed by other
changes, then the other changes are copied into the ProDataSet buffer, and the AVM
sets the
DATA-SOURCE-MODIFIEDflag. This is not an error, however.
The net result of all this is, when PREFER-DATASET is false and
MERGE-BY-FIELD is true, a modified row in the current ProDataSet is
rejected in its entirety and causes an error only when one or more of the same fields have
been changed by another user. Otherwise changed fields in the current ProDataSet row are
successfully written to the database. Changes made by others are copied to the ProDataSet
buffer to be returned to the client, and the CHANGED flag is set.
This may all sound complicated, but in effect it means that the AVM "does the right thing" based on whether you want the new change or the old change to take precedence, and whether or not you want to apply changes field by field or as a whole. The following table summarizes the results.
| PREFER-DATASET setting | MERGE-BY-FIELD setting | If field conflict… | ERROR flag | DATA-SOURCE-MODIFIED flag | What is copied to the DB |
|---|---|---|---|---|---|
| TRUE | FALSE | ProDataSet wins | FALSE | TRUE | All fields in the temp-table row |
| TRUE | TRUE | ProDataSet wins | FALSE | TRUE | Changed fields only |
| FALSE | TRUE | Data-Source wins | TRUE | TRUE | Only non-conflicting fields |
| FALSE | FALSE | Data-Source wins | TRUE | TRUE | Nothing |