Determines whether to and how frequently to update a browse ... or to refresh local memory buffers with changes from other users on the network.[/quote vfp help]
But this does not mean the buffered changes, but the not yet touched records only. Eg user1 and 2 open the table and table burffering is set on. user1 changes record1 and record2, user2 edits record2 and record3, user 2 saves, all before the next refresh cycle, if the refresh does update user1, user1 will see the change in record3, but not yet changes of record2, as he also has began editing this.
We're having a two staged buffering. Buffer of the read in values (rather caching buffer), buffers of edits (write buffer) and then there is the dbf and what's currently written to disc.
When you brows, you think of it as a live view of the dbf file, but in fact it can't be, can it? It's open shared, all users users only see the read in values and this is updated with the refresh mechanism, if you like, or by requerying actively, also indirect by scrolling in the browse. So without having talked about the buffering mechanism accumulating all uncommitted changes of a user, we already have two stages: dbf and what's in memory displaying in the browse. And only up to that level refresh works.
To illustrate you can use this code:
Code:
Close Tables All
* everything is buffered optimistical:
CursorSetProp("Buffering",5,0)
* refresh after 10 seconds
Set Refresh To 10
Cd GetEnv("Temp")
Erase tabTest.*
Create Table tabTest (cText C(5))
Insert into tabTest Values ("this")
Insert into tabTest Values ("is a")
Insert into tabTest Values ("test")
Use
* user1 and 2 open the table:
Use tabTest in 0 Shared Alias user1
Use tabTest in 0 Shared Again Alias user2
*this is what they see
Select user1
Go top
Browse nowait name oBrowse1
oBrowse1.Top = 0
Select user2
Go top
Browse nowait name oBrowse2
oBrowse2.Top = 200
* user1 changes rec1+2
Update user1 set cText = Left(cText,4)+'1' where Recno()<3
Go top in user1
* user2 changes rec2+3
Update user2 set cText = Left(cText,4)+'2' where Recno()>1
Go top in user2
Save this to a prg and run it.
You see user1 and user2 only see their own changes, because nobody saved changes yet.
Now activate the command window and there manually do:
Code:
TableUpdate(.T.,.F.,"user2")
Don't touch anything. After about the refresh time of 10 seconds, the User1 browse will be refreshed.
Record 3 then is "test2" in user1, but the change of record2 is not visible, as user1 also is already changed from
the original value.
Nevertheless: I recommend to never use the refresh mechanism. Let users requery the data before editing, which is automatically done by setting refresh to 0 (always read from disk). This way the moment user1 changes to record 3 he will update that with what's on disk. He
will not see changes before navigating there, but just in time before editing a record he navigate to, so his own editing will always start with what's in the dbf.
He will only see the conflict of editing record1 to "is a1" instead of "ia a2", when he saves his own changes, but you can see the conflict by inspecting user1.cText vs. Oldval() and Curval(): eg in the command window now do:
Code:
Select user1
Goto record 2
? Oldval('cText')
? user1.ctext
? Curval('cText')
So while the user1 browse window shows "is a1", you can determine the initial value (oldval - the old value as it was before editing), thereby detectig user1 changed this field from the old value to a new one. And you can see the changed value in the dbf (curval - the current value on disc in the dbf file), thereby you can also see another user changed this value from oldval to curval. As these all differ you can see the conflict, before it would cause tableupdate() to return .f.
So while user1 will not automatically see user2 has edited the same record, you can see it via code you could put into a conflict check routine before using tableupdate(). You also decide to use tableupdate() with the lForce parameter set .T., which means user1 would overwrite user2 changes and finally in the dbf record2 would become "is a1".
You have all possibilities at hand you need without using the refresh mechanism.
Bye, Olaf.