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!

Opening tables explicitly in the Load() method 1

Status
Not open for further replies.

AndrewMozley

Programmer
Oct 15, 2005
621
GB
I am a little confused in my use of tables within VFP, after all these years !

In my old Clipper applications, I would run the application in folder (say) \users\andrew. My tables (e.g. the customer table, XCUST.DBF, with a tag X1CUST.DBF) would be in that folder.

So, at the beginning of my application, I would say something like

USE XCUST INDEX XCUST ALIAS Cus
SELECT Cus
SET ORDER TO TAG X1CUST
(And later on)
SEEK “A001” or something like that

I appreciate that there were no complications of multiple windows and forms.

In my VFP applications I normally include the “USE XCUST ” sequence in my LOAD method. However I notice that if I do not do so, I can still bind (say) Textbox controls to this table by specifying the control source as (e.g.) XCUST.Accno.

So, my question is : If I explicitly open a table in my LOAD method, am I competing in some way with the bound textbox control which can find the table anyway without the benefit of the USE command?

I also noticed that if I include the USE . . . INDEX command, my TableUpdate() commands fail with a warning message that I need to have buffering switched on. This is certainly set as a property of the form (Pessimistic). It seems that I additionally need to issue a CURSORSETPROP() command. Why is the buffering property not applied automatically to tables which I open in the form?

A rather similar question relates to the use of the data environment : If I use the data environment, should I avoid explicitly opening tables in my LOAD method? The matter is slightly complicated because I usually use an Alias (USE XCUST ALIAS Cus). Is this approach compatible with binding controls?

Thanks. Andrew
 
You do need to indicate that tables should be opened in the form. It's your choice whether to put them in the Data Environment and let the DE open them, or to open them explicitly in the Load method. Either way works, and it's a matter of personal preference, but you don't need both.

As for USE xxx INDEX yyy, you should never use that. Specifically, you should never use the INDEX clause, because individual IDX indexes are a bad idea. All your permanent index tags should live in the structural CDX file, that is, the CDX with the same name as the DBF. That file opens automatically whenever you open the table, so you never have to worry about whether tags are up-to-date; they always are. If you want to specify a particular tag when opening a table with a structural CDX, use the ORDER clause rather than the INDEX clause.

Finally, you can specify an alias when adding tables to the Data Environment. If you look at the property sheet when a table is selected, you'll see an Alias property. Just set that.

Think that's all your questions.

Tamar
 
Thanks for your reply, Tamar.

Certainly the use of .idx indexes is unusual; I never use them. I use the standard compound .cdx indexes and note that they are automatically opened by VFP.

Thanks for the mention of the Alias property within the data environment – I had not noticed that.

In the matter of buffering : if pessimistic buffering is specified on the form properties, this is not applied to tables which are explicitly opened in code, and this is what had confused me.

Thanks again. Andrew
 
Adding to Tamar's comment.

IMO, it's bad to apply the index order on the USE command. It actually takes longer to open the table because VFP opens the table, positions the record pointer to the first record, then opens the index and repositions the index pointer to the first record in the index.

A better method is to USE Table, then in a separate command, SET ORDER TO TAG SomeTag. In this case, the record pointer is not repositioned when the index is set. I've seen this be 2-3 times faster.

Craig Berntson
MCSD, Visual C# MVP,
 
Let me adress the questions I see still unanswered (and you could make this several threads, though I see how the questions are related to the overall topic of data binding, it's ok, but it may cause severl threads of discussuion harder to follow in tek-tips in a single thread)

>...However I notice that if I do not do so, I can still bind (say) Textbox controls
>to this table by specifying the control source as (e.g.) XCUST.Accno.

Simply tested: I created a form with a textbox, set it's controlsource to sometable.somefield, and it errors with "Alias...not found Unbinding object text1."

So in general, this will not work. This may work, as you already have a table open and your form has no private DE, but in general it will not work.

>Why is the buffering property not applied automatically to tables which I open in the form?
The help topic on Buffermode says: "The BufferMode property setting will override any buffering settings made to form cursors prior to the form Init method, including those made in the form Load method." So this is applied later, not at Load. Also Buffermode 1 or 2 make a grid control do table buffering, while single row controls like textbox or editbox buffer in record mode. This is getting messy, if you bind the same table to a grid and single row controls.

You can make use of CURSORSETPROP("Buffering",5,0), the 0 as the workarea has a special meaning, as in "USE sometable IN 0" it means an unused workarea, so this is really presetting that Buffering mode to all later opened Aliases.

Also see at the properties of a Table you put into the DE: It has a "BuffermodeOverride". This overrides this again. So in the end your best bet is to set it individual. The risc of CURSORSETPROP("Buffering",5,0) is, that you may not remember that this influences all data and if later updates fail because of MULTILOCKS not being set ON it's harder to find the reason. Besides it is a good idea to make that setting ON a default.

Also remember several settings are per Datasession, so it's not unusual to make a per cursor/table CURSORSETPROP() in a data access class, which is the failsafe way of overriding any override or combination of controlbased or form based decision made about buffering.

Also you may want to index a view or cursoradapter, which both are query results making use of permanent indexes, but themselves not being indexed. And that can only be done, before setting them to a buffering mode, so you would then set Buffering to 0 temporary and set it back to 5 afterwards. I tend to think it's easier to wait with the buffering, after the data is fetched as needed and prepared with indexes for fast sorting and editing. The buffer is still empty then and so you can shift setting Buffering to that moment at the end of initialisation. So rather set CURSORSETPROP("Buffering",0,0) and set your buffering as the last step of opening a table. And set it to 5 (optimisitc table buffering), that still allows you to update single rows, revert single rows, commit all or revert all changes etc. as you like, and allows shared access and concurrent editing in contrast to pessimistic buffering, which actually isn't about buffering anyway, but about locking.

And that's another topic.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top