Hi,
We are using TMS RemoteDB with Firebird in VCL application. We've run into a concurrency problem and would like advice on the recommended approach.
Setup
One table has three related fields: total = price * quantity. On the client, total is calculated in XDataWebDataSet1.OnBeforePost:
delphi
procedure TForm1.XDataWebDataSet1BeforePost(DataSet: TDataSet);
begin
DataSet.FieldByName('total').AsFloat :=
DataSet.FieldByName('price').AsFloat * DataSet.FieldByName('quantity').AsFloat;
end;
Scenario
Initial record: quantity = 1, price = 1500, total = 1500
- User A and User B open the same record at the same time.
- User A changes
quantityfrom 1 to 2. OnBeforePost calculatestotal = 2 * 1500 = 3000. Saved:quantity = 2, total = 3000. - User B only changes
pricefrom 1500 to 2500. Since User B still seesquantity = 1, OnBeforePost calculatestotal = 1 * 2500 = 2500. Saved:price = 2500, total = 2500.
Result in the database
quantity = 2, price = 2500, total = 2500
The correct total should be 2 * 2500 = 5000. Each user's update is valid on its own, but the combined result is inconsistent because User B's total was calculated from stale data.
Questions
- What is the recommended way to handle this in XDataset/RemoteDB? Is there built-in support for optimistic locking (e.g. a version/timestamp field) so that User B's update is rejected or User B is notified that the record was changed?
- Should fields like
totalbe calculated on the server side instead (e.g. in an XData service method, an entity event, or a Firebird trigger) rather than in the client's OnBeforePost?
What is the best practice for this pattern, since many of our documents (orders, invoices) have similar dependent fields?