Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to stop automatic updating of cursor buffers? 1

Status
Not open for further replies.

markftwain

Technical User
Jul 12, 2006
108
Hi

I read from an optimistic table-buffered table, "encounters", into a custom object and then present the properties of that object to a form for editing.

This same record and form is then accessed by another user in a seperate run-time vfp session, i.e., this is a multi-user application.

The second user edits the record and saves it while the first user is editing the record.

It appears that when the second user saves the record, the table and the buffer of the first user is updated immediately. Thus for the first user, curval()= oldval() and I am unable to detect a conflict when user1 performs a tableupdate().

Bottom line: I need to detect exactly which fields user1 changed in a multi-user environment. What am I missing?

Additional information:
I am using vfp9, sp2
It makes no difference if the encounter form is using a private datasession or not.
I am not using cursor adaptors.
A thorough search reveals only one use of tablupdate() to save the object back to the disk and no uses of revert() anywhere.

Thank you for your consideration.
 
I've seen curval()=oldval() in this scenario when a field gets saved unchanged. (The name was "Smith" before and is still "Smith" but we Tableupdated the record because of other fields.)

However, there's a third value you need to use in detecting changes: your currently buffered value. Compare table.fieldname against curval() and oldval().

It's a three-way contest.
 
Dan is right in that you have three values, the curval(), the oldval() and the field of the otimistically buffered table.

And in fact even with REFRESH set to 0,-1 if a table is buffered you'll see the buffer first and not what's on disc, if you bind a field to a form.

See what happens here:
Code:
Clear

Set Multilocks On
Set Refresh To 0,-1

Create Table tabTest (iID I Autoinc, cText C(1))
Insert into tabTest (cText) Values ('A')

Use tabTest In 0 Again Alias tabTest2

CursorSetProp('Buffering',5,'tabTest')
CursorSetProp('Buffering',5,'tabTest2')

*user 1 changes A to B
Replace Next 1 cText With 'B' in tabTest
*user 2 changes A to C
Replace Next 1 cText With 'C' in tabTest2

? 'user 1 before tableupdate'
? 'direct',tabTest.cText
? 'oldval',Oldval("cText","tabTest")
? 'curval',Curval("cText","tabTest")

? 'user 2 before tableupdate'
? 'direct',tabTest2.cText
? 'oldval',Oldval("cText","tabTest2")
? 'curval',Curval("cText","tabTest2")

? 'tableupdate tabTest: '
?? TableUpdate(.f.,.f.,'tabTest')

? 'user 1 after successful tableupdate'
? 'direct',tabTest.cText
? 'oldval',Oldval("cText","tabTest")
? 'curval',Curval("cText","tabTest")

? 'user 2 before tableupdate'
? 'direct',tabTest2.cText
? 'oldval',Oldval("cText","tabTest2")
? 'curval',Curval("cText","tabTest2")

? 'tableupdate tabTest2: '
?? TableUpdate(.f.,.f.,'tabTest2')

? 'tableupdate fails, because user 1 changed from A to B'

user 1 sees his change B, user 2 sees his change C, user 2 update fails, but he still does not see B, he still sees his value C, even though refresh is not only set to read directly from disc. The buffer is never updated from disc, it's a one way buffer written to from the local client only.

After user 1 already sees B as direct, current and old value, user b still sees his C directly, A as the oldvalue read in and B as the current value from users update, but not as his current value.

So reading from the field gives the buffer value, curval() is the current value on disc and oldval() is the value initially read.

Bye, Olaf.
 
Yes...but it is not working for me.

I think maybe my English is bad. Yes table.fieldname for the first user is different from curval() and oldval(), but curval() and oldval() both change for the first user after the second user has saved. I can understand why curva() will change--it should, but without any form of tableupdate() or tablerevert() on the first user's part, I do not know how or why oldval() is changing to match. That is, the first user has done nothing but stare at the screen and both his oldval() and curval() are changed. When the first user goes to save with tableupdate(1,.f.,"encounter"), no data conflict is detected thus overwriting all the fields the second user edited. Page activation has only thisform.refresh. (My ultimate goal is to only save the fields the first user actually edited.)

I don't know if it matters any, but I am testing this by running the encounter form concurrently on the same machine using seperate runtime sessions of vfp9 in non-private data environments. I also routinely use select...sql with buffering=.t. to populate grids.

Thank you very much.
(Sorry for the long response time, my internet connection is poor.)
 
Problem solved.

For other newbies like myself,

My default settings for vfp:
Tools-->options-->data--Table Refresh Interval (sec)
was set to 5.0000 seconds. When this is changed to 0 seconds, the oldval() remains as it was initially read on the form startup. Any other value, including -1 causes the oldval() to replicate the curval() for the first user.

The simpliest solution was to put in my startup.prg:
set refresh to 0,0
and all works well.

Thank you for your time, "set refresh to.." was the key.
(Microsoft did an excellent job with vfp, I will sure miss it.)
 
Well, if you change refresh to 5, like you did, and there are more than 5 seconds between the save of the first user and the change of the second user, indeed the second user begins with the new data from user 1. So there is no update conflict, as then it's two sequential changes instead of concurring.

What's not happening perhaps is the visual update. REFRESH does no form refresh, just the table refresh of the not yet buffered records.

You may think once you turn on table buffering the oldval() of all records are saved, but that's not the case, table buffering also just buffers records, but multiple records. As long as user 2 does no change the record is not in the buffer and changes of user 1 do come in.

And yes, if you don't want that kind of updates you turn off refreshing by set refresh to 0,0

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top