Rajesh said:
So, basically, before saving, I need to check all those fields which are supposed to be edited by other users also for changes made by others.
No, you overcomplicate it. You can only be influenced by changes other users already saved. Their buffers are not in your access, and their saving of their buffer happens in their save routine, that's not your business.
Your "investigation" only begins with your own users changes. They can only conflict with values in the DBF in these changed fields, not in all. Collisions can only happen with what you changed according to GETFLDSTATE. No more. So as I already initially said, you want to know too much. You don't need to know about all changes of other users, not even in the record you handle currently. It doesn't matter if curVAL and OLDVAL differ in fields that are unchanged according to your own GETFLDSTATE, those are untouched, you don''t write back the OLDVAL, if your userr didn't touch that field value, you just don't handle that field at all.
So, all in all you only need to care about the fields that are changed and submitted by your user. And for these fields it is interesting to know whether CURVAL and OLDVAL differ, as that means these fields were not only changed by your user, but other users as well, they even already saved - managed to save - those changes without conflict. It doesn't even matter if it were already two or three changes by other users.
I and Mike even differ in what we think happens. You seem to be afraid that you overwrite fields with their old value, that were changed by other users, even though your user didn't change them. But that doesn't happen. TABLEUPDATE skips fields your user didn't touch, so there is nothing you need to protect in these fields. You only care about the fields your user wants to change right now and which also one or many other users already changed in the DBF from OLDVAL to CURVAL. When you're finished with saving your buffer is empty. The fields' CURVAL is what you just saved and becomes OLDVAL if you allow the editing session to continue. So, just as a side note, it can prevent collisions for your user, if he saves more often than just at the end of all his editing.
But the basis of your conflict detection is just fields that GETFLDSTATE reports as changed by your user. It only reports changes of your user, not of others, as it's about your users alias/workarea and buffer, locally. You don't detect what fields other users changed with GETFLDSTATE. You detect that by the difference in OLDVAL vs CURVAL. Notice that CURVAL is not your users' current value, it's the current value of a field in the DBF file. In your workarea, FIELD reads either the buffered change or OLDVAL, if there was no change by your user in your workarea. The OLDVAL won't matter if this field is not having the status of being changed, as TABELUPDATE then skips it in his UPDATE statement. You don't need to be afraid of overwriting changes other users already saved with OLDVALs, the overwriting can only happen, if your user also modified the OLDVAL he read to something new. Please read about GETFLDSTATE() in the help file.
Notice also, that if you insert a record into a buffered table, this record is not yet in the DBF at all before TABLEUPDATE, there will be no other users conflicts with such records, so we only need to consider talking about records you initially loaded into your form, for example simply by binding controls to fields that read at least one record. Only those already existing records you modify can even have conflicts with other users' changes. Only those records have a CURVAL in the DBF at all.
Maybe you also didn't yet get that if you turn on buffering, the changes a user makes don't go into the DBF directly, Your changes are buffered, thats why this is caled buffering at all. You only plan to save those values. The only way such a buffered value automatically is stored to the DBF is when you only use record buffering and skip from a changed record to the next. Because the buffer is not meant to have a second record buffered, too, you then implicitly do a TABLEUPDATE without code. And you can get errors with conflicts, then, which you then can't handle as gracefully as keeping full control about the point in time and code for saving with TABLEUPDATE.
Rajesh said:
I will take values from other users, update my buffers and then go for TABLEUPDATE().
No, if your user didn't change fields it's of no interest what other users did to them, they are not touched by your user saving his changes, also not with lForce=.T.
Let's just look at the exact case where you need to act: You find out your user has changed field "FIRSTNAME" by GETFLDSATE. You find out by comparing CURVAL("FIRSTNAME") and OLDVAL("FIRSTNAME") that another user changed the value, too. You can't find that out just by comparing CURVAL("FIRSTNAME") with FIRSTNAME itself, that just will tell you your user changed FIRSTNAME and you know that already, as you found out by GETFLDSATE() that your user changed this field. You know that without knowing ODVAL or CURVAL, as VFP just keeps track of this state of the field. States of a field can be 1- loaded and unchanged, 2 loaded and modified, 3 new and at the initial default value or 4 new and modified from the initial default value. This is part of the buffer information VFP keeps up to date no matter with which commands or controls you modify a workarea. To conclude this situation:
1. your user changed FIRSTNAME from OLDVAL to something buffered you want to save now. Another user (or even many already) changed that field FIRSTNAME from OLDVAL("FIRSTNAME") to CURVAL("FIRSTNAME"), so these two values differ, then you now you run into a conflict if you do a TABLEUPDATE. And I recommend not to fix this by REPLACE FIRSTNAME with CURVAL("FIRSTNAME") but by overrideing the fied state. You tell VFP to not save your users change, by overrideing the field STATUS, not its value. So it is
skipped in the TABLEUPDATE(), either just that field is skipped or the whole record is skipped from updating - if there are no other field changes. You don't need to be actively the savior of CURVALs by "inheriting" them into your planned change. Insteead you just exclulde your field change from the overal buffer submission.
Chriss