Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.
One of the loudest religious arguments in FoxPro 2.x and older versions was whether to edit fields directly or edit memory variables and then commit the changes to the fields. The proponents for each side could produce all sorts of arguments for why their approach was The Right Way. We’re glad to report that the argument is over, and neither side wins. Or maybe both sides win. We definitely win.
Built-in buffering is one of many cool features of Visual FoxPro. Now, you can write code that appears to edit fields directly, but really works on copies of the fields. When you turn buffering on (either through form properties or with CURSORSETPROP()
), FoxPro maintains several buffers containing the data in its different states. No more SCATTER MEMVAR or GATHER MEMVAR.
Your code looks like it addresses the fields, but in fact it’s really talking to one of these buffers. When the user makes up his mind whether to save or discard his changes, you can either commit the changes to the real table or throw away the buffered changes. One function call (either TableUpdate()
or TableRevert()
) does the trick in either case.
FoxPro not only gives you a copy of the data to work on, but it keeps a copy of the original data and the current status of the data, in case someone else changes it while you’re working. No more making an extra COPY TO
compare with the network.
Visual FoxPro has two buffering modes, each of which can be used in two different ways. The two modes are optimistic and pessimistic, referring to the locking scheme used. With the pessimistic approach, a record is locked as soon as you make any change. That way, no one else can change it until you release the lock by committing or reverting the buffer. With optimistic locking, the record isn’t locked until you attempt to commit the changes. You run the risk that someone else will make changes at the same time, but records are kept out of circulation for the shortest possible time. There’s no need for a religious war over buffering modes because each has its place. Use pessimistic locking for sensitive changes that must go through. Use optimistic locking for everything else. (Views always use optimistic buffering.)
The other buffering choice is whether to buffer individual records or entire tables. Again, this isn’t all-or-nothing. You can use row buffering for some tables and table buffering for others. If you don’t specify otherwise, Visual FoxPro uses table buffering when you use a grid for a table, and row buffering for all other tables.
With a buffered table, you can examine the current value of a field, the value it had when you started working with it (OLDVAL()
—actually, the last time you committed it) and the value it has now on the network (CURVAL()
). You can also get information (GETFLDSTATE()
) about the status of any field: Have you changed it? Have you deleted the record it belongs to? Is this a new record? And so forth. You can also find all the records that have changed using GetNextModified()
.
Using the various functions that control all this, you can write code that makes intelligent choices when conflicts arise, and only bothers the user if it doesn’t know what to do.
In addition to buffering, Visual FoxPro lets you wrap updates (both local and remote) in transactions. With a transaction, everything you do is tentative. If one part of an update can’t be completed, you can roll the whole thing back. No more worrying about adding the invoice header without the details. Wrap it in a transaction, and you save header and details or nothing at all.
Begin Transaction, BufferMode, BufferModeOverride, CursorGetProp(), CursorSetProp(), CurVal(), End Transaction, GetFldState(), GetNextModified(), OldVal(), Rollback, SetFldState(), TableRevert(), TableUpdate()