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!

Form field receives wrong data 2

Status
Not open for further replies.

k2a

Programmer
Jun 26, 2012
133
DE
Hi to all,
On my development system I do access either the local or remote database. When running my application a splash screen should show me which database has been selected.
On the splash form’s Data Environment is a table systeminfo and the ControlSource of a field points to systeminfo.dbversion, the value in this field should show me which database is currently selected.

However, it always shows me the value from the local source regardless whether the remote or local source is selected.

In an ini-file there are both database paths and my app class controls the database selection. When I step through my main.prg I can see that the remote path from the ini-file is catched and used by the method opendatabase to select the remote database.
All this is done executing: oApp = CREATEOBJ('exapp')
DO FORM forms\Systeminfo is the next command to run my splash screen.

At this point I expect that the data systeminfo.dbversion comes from the remote source but is does not.
What could be the reason for this behavior?

Regards,
Klaus
 
Klaus,

If you look at your cursor object in the Data Environment (that is, the object representing SystemInfo table), you will see that it has a property named CursorSource. This contains the absolute path to the physical DBF file. Also, if the table is in a DBC, the Database property contains the absolute path to the DBC.

The paths in question will be the paths to the table, at the time that you added them to the DE. Presumably, these point to your local version. It is these paths that determine which table to open, regardless of how you open the database.

However, if VFP can't find the hard-coded path when the form is instantiated, it will look for the table in the default directory and the search path, as you would expect. So, the trick is to make sure it can't find the hard-coded path, for example by ensuring that the directory in question is not present on your system at that time, or that it does not contain the table in question. In that case, VFP will look along the search path and find the correct table.

If that's not possible, set the Data Environment's AutoOpenTables property to .F., and open the table yourself in the form's Init. Or, remove the table from the Data Environmet, and open it programmatically in the Init.

If I've understand the problem correctly, I think that will do what you want.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
I think Mike has pinpointed the reason you always see the table of the local database, despite opening the remote database. Also see, if you included the database in your project. I don't fear this has the dbc and dbfs compiled into the EXE, the defaults are not to, only to have them in the project manager, but what I fear is, this database is automatically open and if you open the remote database that's fine, but will not set it to be the active database. And that also hits you, if you USE some.dbf in code.

Additional to OPEN DATABASE \\share\data\your.dbc you should also SET DATABASE TO \\share\data\your.dbc to make it the currently active database.

That already solves the situation for opening tables via USE tablename, still foxpro does encode full paths into the DE objects and that can be redirected to the currently active database in the easiest way by renaming that local database folder, so VFP is forced to look elsewhere, or by using some code to adapt the paths. Tamar has described that in the Hackers Guide, I think. You can put code into BeforeOpenTables to change DE objects CursorSource and Database properties to the currently active DBC(), before they are opened to open the correct ones.

The typical solution is to not work with the DE, though. You have more control by adding code, that USEs all tables needed or even use application frameworks like VFX, VFE, Pro Matrix or something else, doing data access OOP style with data access objects. Admittingly the DE makes it easy to drag&drop fields on a form to create form elements bound to data automatically, but in the end some behaviors of the DE are not as easy to handle, also because they occur even before you get control over it in form.init, where you can send in filter parameters, for example.

Bye, Olaf.
 
Just to add a word ....

On reflection, I think the easiest solution is simply to remove the table from the Data Environment, and to explicitly open it in your code.

I said earlier that you should open the table in the Init event. It would be better to do it in the Load. That way, you can be sure that it will be available at initialisation time for any of the controls on the form that needs it.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Mike and Olaf,
Thank you for your in-depth and comprehensive explanation. I would never figure out that by myself.

First I renamed my local database and run the EXE, to my surprise VFP found the remote database just as you said.

Next added the command SET DATABASE TO \\share\data\your.dbc after the command OPEN DATABASE \\share\data\your.dbc but this did not change anything. Finally tried what Mike suggested, set the Data Environment's AutoOpenTables property to .F. and opened the table in the form's Init. That solved my problem.

May I ask the experts another question?
Occasionally, it is necessary to make modification to the database such as adding views or change field properties. This must of course first be done on my local database. If the changes turn out to be satisfactory I duplicate all those changes into the remote database, because the contents of both databases are different.

Is there a way to find out if both databases are structural the same?

Regards,
Klaus
 
Glad you've got it working, Klaus.

Regarding you other question, Tamar has posted some code that will compare two DBCs, to check that they have the same tables and that these have the same record counts. You can see it here:

(Tamar's code doesn't cater for views, but it should be very easy to modify it.)

That said, I'd suggest an alternative approach. When you need to modify the database, write a script to do it. The script would be a normal PRG fle, using ADD TABLE, ALTER TABLE, and similar commands. Test that against the local database. Then, when you're happy that it's working, just run it against the remote version. That way, you can be sure two copies are always in sync.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
>Next added the command SET DATABASE TO \\share\data\your.dbc after the command OPEN DATABASE \\share\data\your.dbc but this did not change anything.
I said so :)
I said this will solve the problem, if you use tables programmatically.

To keep two databases in synch, there is a good tool available worth it's price: Stonefield Database Toolkit. It can forward structural changes and as a plus also can repair some DBF defects.

Bye, Olaf.
 
Mike, I like your alternative approach, super idea.

You wrote "Tamar's code doesn't cater for views, but it should be very easy to modify it."
But what statments can be used to cater views?

Regards,
Klaus
 
Klaus,

To modify Tamar's code to cater for views, take a look at the two calls to ADBOBJECTS() near the top of the code. Because these receive the word "TABLES" as their second parameter, they will each fill an array with the names of the tables. If you were to pass "VIEWS" as that parameter, they would create an array with the names of the views.

Unfortunately, you can't combine the two in a single call. But you can call the function twice (or rather, four times: twice for the first database and twice for the second), and combine the resulting arrays. The rest of the code would then work as at present.

But, given that you are happy with my alternative solution, I would really suggest you go with that. It's a fairly common way of handling this situation, and is perfectly straightforward.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top