Information générale
Catégorie:
Base de données, Tables, Vues, Index et syntaxe SQL
Doug,
>>This code is actually very fast.<<
It uses minimum processing time as long as I do not make it a multi-purpose program where I would need to pass it the name of the table/view and the names of the 'summarycount' fields, which would require additional time. (I need to look into that, however, as I might need to use this same program for resolving conflict in another table/view.) Here's how I have tailored it for my own use:
*------------------------------------
local lnFields, lnI, llConflict, llOtherUser, llSameChange, luOldVal, luCurVal, luValue, llThisUser
lnFields = afields(laFields)
FOR lnI = 1 to lnFields
*
* Reset variables:
llConflict = .f.
llOtherUser = .f.
llSameChange = .f.
*
* Determine the name of the current field being processed.
lcField = laFields[lnI, 1]
*
* Save original value and value from disk. Note that if the current record is a new record,
* oldval() and curval() will return .null. values.
luOldVal = oldval(lcField)
luCurVal = curval(lcField)
luValue = evaluate(lcField)
IF !isnull(luOldVal) and !isnull(luCurVal)
*
* Compare oldval() and curval() to determine whether or not another user on the network
* changed the field value while the current user is editing it.
llOtherUser = luOldVal <> luCurVal
*
* Determine whether or not this user has made changes to the field himself.
llThisUser = luValue <> luOldVal
*
* Determine whether or not the field has changed.
llSameChange = luValue == luCurVal
ELSE
*
* In cases where oldval() and curval() return a .null. value, automatically set llOtherUser and
* llSameChange to .f.. It would be a waste of processing time to assign 'blank' value to luOldVal and
* luCurVal only to determine that llOtherUser and llSameChange will always have a value of .f. if a
* new record is in the process.
ENDIF
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 upper(lcField) = 'CTD_NSTAINCT' or ;
upper(lcField) = 'CTD_NREPAIRCT' or ;
upper(lcField) = 'CTD_NWATERWASHCT' or ;
upper(lcField) = 'CTD_NBRCT' or ;
upper(lcField) = 'CTD_NWORNCT' or ;
upper(lcField) = 'CTD_NCANCELCT' or ;
upper(lcField) = 'CTD_NSHPMISCCT' or ;
upper(lcField) = 'CTD_NISSUECT' or ;
upper(lcField) = 'CTD_NRCVDCT'
lnOtherUserChange = luCurVal - luOldVal
lnThisUserChange = luValue - luOldVal
*
replace (lcField) with luOldVal + lnOtherUserChange + lnThisUserChange
OTHERWISE
llConflict = .T.
ENDCASE
NEXT
return llConflict
*-----------------------------
>>You really don't have any way around using code like this if you're going to use optimistic buffering.<<
I agree. I still found conflicts even after I switched to an updateable view.
>>With pessimistic buffering, you don't need to do conflict resolution because there's no possibility that someone else edited the record at the same time. However, that causes contention issues (I lock the record, then go for lunch, leaving you unable to do your work).<<
Yup! I did not think that that was the solution either.
I am going to test these changes in production. I will let you know how it goes.
Thanks,
Evelyn
Précédent
Répondre
Voir le fil de ce thread
Voir le fil de ce thread à partir de ce message seulement
Voir tous les messages de ce thread
Voir tous les messages de ce thread à partir de ce message seulement