Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Cannot RLock()
Message
From
07/06/2002 13:34:13
 
General information
Forum:
Visual FoxPro
Category:
Databases,Tables, Views, Indexing and SQL syntax
Title:
Miscellaneous
Thread ID:
00665258
Message ID:
00666077
Views:
19
Hi Evelyn.

>I am worried that if two or more users can grab the same record at the same time, since only one of them will be able to save first, someone's change could be overwritten by the other user. Depending on who gets to save his work first, the counts would come up short.

Let's say two users access the same record at the same time, and the summary count for both is 5. Then User A adds 1 to the count (so it's 6) and saves. User B (who still sees 5) adds 2 to the count (so it's 7, but really it should be 8, given User A's change) and saves. What happens next is that for User B, the TABLEUPDATE() function fails and if you use AERROR() to check what went wrong, you'll find error 1585 occurred, meaning that the user tried to change a record that another user changed.

Different applications can handle this in different ways, but one way you might handle this is to use spin through all the fields in the current record and use a combination of the value this user has, the original value before they changed it (OLDVAL()), and the current value as it is on disk (accounting for changes other users made, CURVAL()). Here's the overall logic:
lnFields = afields(laFields)
for lnI = 1 to lnFields
  lcField      = laFields[lnI]
  luOldVal     = oldval(lcField)
  luCurVal     = curval(lcField)
  luValue      = evaluate(lcField)
  llOtherUser  = luOldVal <> luCurVal
  llThisUser   = luValue  <> luOldVal
  llSameChange = luValue  == luCurVal
  do case

* The other user edited this field but this user didn't, so grab the new
* value.

    case llOtherUser and not llThisUser
      replace (lcField) with luCurVal

* The other user didn't edit this field, or they both made the same change,
* so we don't need to do anything.

    case not llOtherUser or llSameChange

* Uh-oh, both users changed this field, but to different values, so we have a
* "real" conflict. In the case of the SummaryCount field, we'll handle it by
* applying changes both users made. For any other field, flag that we have
* a conflict.

    case lcField = 'SUMMARYCOUNT'
      lnOtherUserChange = luCurVal - luOldVal
      lnThisUserChange  = luValue  - luOldVal
      replace (lcField) with luOldVal + luOtherUserChange + ;
        luThisUserChange
        
    otherwise
      llConflict = .T.
  endcase
next

* If we don't have a "real" conflict, force all the changes.

if not llConflict
  llSuccess = tableupdate(2, .T.)
else
*** handle a "real" conflict in some way eg. ask the user what to do
endif
By using the REPLACE command to force this user's record to contain the values we want, and then forcing the update (the .T. parameter in TABLEUPDATE()), changes both users made to the SummaryCount field are handled.

Hope this helps.

Doug
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform