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 gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Specifying Dynamic data path (physical folders) in DataEnvironment of form 4

Status
Not open for further replies.

Rajesh Karunakaran

Programmer
Sep 29, 2016
549
MU
Hi Team,

Most of our forms in application has data environment and we use a fixed path, i.e "Data" folder right under the application install folder. I want to make this dynamic/configurable, i.e users can have the data in another folder or even another drive which they can (or may be us when we install).

Usually, during development we add the tables from the 'Data' folder onto the Form's DataEnvironment. But now, if we do not know the folder in advance, what is the correct way to add tables in DataEnvironment?

Thank you in advance
Rajesh
 
Rajesh,

If, at run time, the data environment can't find the tables in the specified path, it will look for them along the VFP search path. So, providing the path specified in the DE (in this case, <application folder>\data) does not exist on your target machine at run time, you can place the folder anywhere where the application can find it.

So you could store the path to the data folder in some suitable storage mechanism, such as an INI file, the Registry, or simply a free table in the application folder. Your executable would read that, then add it to your SET PATH.

On a separate point, it is generally considered a bad idea to store your data in a sub-folder of your executable folder. If the user installs the app in Program Files (which is the default for most install programs), then your user could come up against User Access Control issuese. Better store it in a dedicated directory, or better still in a sub-folder of AppData.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi,

Please have a look at the below code, which you'll have to put in the BeforeOpenTable method of your DE. Unfortunately the http link does not exist anymore

Code:
* [URL unfurl="true"]http://support.microsoft.com/kb/128996/en-us[/URL]
LOCAL lcDataPath, lnStartPos, i, lcObjClass, lcDataName, lcNewDataPath, lcObjName
LOCAL loCursor as Cursor

lcDataPath = "C:\YourDataFolder" &&& has to come from outside of this code snippet

IF !EMPTY(lcDataPath)
   = AMEMBERS( laCursors, THISFORM.DATAENVIRONMENT, 1)
   = ASORT( laCursors, 2)

   lnStartPos = ASCAN( laCursors, "Object", -1, -1, 2, 15)
   IF NOT EMPTY(lnStartPos)
      FOR i = lnStartPos TO ALEN(laCursors, 1)
         IF laCursors[ i, 2] = "Object"
            lcObjClass = "ThisForm.DataEnvironment." + laCursors[ i, 1] + ".class"
            IF EVAL( lcObjClass) = "Cursor"
               lcObjName = "ThisForm.DataEnvironment." + laCursors[ i, 1] + ".Database"
               lcDataName = EVAL(lcObjName)
               lcNewDataPath = ALLTRIM( lcDataPath) + ALLTRIM( SUBSTR( lcDataName, RAT( "\", lcDataName) + 1))
               loCursor = EVAL( "ThisForm.DataEnvironment." + laCursors[ i, 1])
               IF NOT EMPTY(loCursor.Database)
                  loCursor.DATABASE = lcNewDataPath
               ELSE
                  loCursor.CursorSource = ADDBS(ALLTRIM(lcDataPath)) + JUSTFNAME(loCursor.CursorSource)
               ENDIF
            ENDIF
         ELSE
            EXIT
         ENDIF
      ENDFOR
   ENDIF
ENDIF
RETURN

hth

MarK
 
It's one reason to not use the DE and why frameworks offer their own data access objects.

But as Mike says there is that automatic finding mechanism.

The other mechanism most often referred to is Hackers Guide and other places running a routine in BeforeOpenTables event to adapt the Database property of cursor objects in the DE.

Since you can use Cursoradapters in DEs you also have better ways, as you have more code and fewer automatisms, ie you can, of course, specify the DBC to use as data source in the init of a cursoradapter, and that may easily get its dbc path to use from some configuration.

Especially now we have the separate DE class and you can use a forms DEClass and DEClasslibarry properties to make use of thus instead of the default DE of a form. It also allows you to have a class hierarchy of DEs and use Des on several forms without redoing them. So this is an enhancement of OOP usage in VFP.

Just to hint on a bad design decision: Don't just right click and "Add Cursoradapter", you get a native DE and would not profit from being able to create classes yourself. Every CA you add this way starts from scratch and you don't want to redo a lot of things you could do in a vase CA clas, which includes simply opening a DBC (of it's not yet openeed) by base Ca class init code.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Mike,

Thank you for that simple and straight way. In fact, I also was thinking that way.
However, I need to think about a way to force my application to take the data only from the folder that I define. Now, if 'Data' folder is there both in C drive and D drive, it will take from the first place mentioned in the search path, isn't it?

Rajesh
 
Dear Mark,

Thank you for the code! I will try that.
I am still have to choose from the most appropriate way.

Rajesh
 
Dear Olaf,

Thank you very much.
I think, I should go for the simplest method (yet to choose from multiple suggestions). Need to ensure that is the appropriate one as well.

Rajesh
 
Now, if 'Data' folder is there both in C drive and D drive, it will take from the first place mentioned in the search path, isn't it?

That is correct. But the approach I suggested was that you don't have the folder in more than one place. Or, put another way, that you do not have more than one copy of the folder. So, on that basis, there would be no reason to have it on both the C and D drive.

Now, having said all that, Olaf wrote that all this is "one reason to not use the DE". I agree with that. I don't use the DE in forms, nor do I use the BeforeOpenTables event. I prefer to use my own data manager class, which is responsible for finding and accessing all the data in my application. But that's just my personal choice. There is nothing wrong with the other approaches suggesed here.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I run a little routine just before each compile to point the dataenvironments at a very unlikely folder.

Thus if I develop with the data in the folder under the dev directory, as long as I run the routine before I make the application, VFP won't remember that.

I do something similar with all the report forms too, to remove any printer specific stuff before compilation.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
Hi Mike,
Yes, you are correct. Generally, there is no need/chance to have that data path in various places in the same computer.

By the way, when you use your classes or form's 'Load' method to explicitly open tables, you use the SETCURSORPROPERTY to make them Buffered?

Rajesh
 
You have mainly two options in a situation data is in several places: Don't SET PATH to both of then. so VFP won't find the irrelevant one. or explicitly set the database property.

What you can't avoid is VFP finding the database you used for development on your own PC, but there you could (temporarily) rename the development data folder. This part is actually quite nice:

1. It ensures you use your development data and not muddle with any production database
2. If you never install in that same place on end clients every use of DEs goes through searching within SET PATH directories. You want the one in D: and not in C:? Well, then don't add the C: database path to SET PATH
3. You're able to set the exact database going through the objects.

If you stop time it takes, I have not tested, but even the timeout in not finding data in the original place before even starting to search in SET PATH, you have a timelag that's longer than going through perhaps just 10 or fewer objects of the DE and setting their database property before they open the table or view.

Yes, going from form DEs to DE class and using Cursoradapters is a major change and takes the longest time, it's obviously meant for new development.

And as you asked Mike about settings you can do in the DE objects and the DE itself. What you do with CURSORSETPROP for workarea 0 means you do it for all future dbfs or views, so you can have a general buffer mode without the need to program it for each workarea.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Dear Olaf,

Olaf said:
What you do with CURSORSETPROP for workarea 0 means you do it for all future dbfs or views, so you can have a general buffer mode without the need to program it for each workarea

I think I have not used that way yet. If it's in form DE, I set it there for each table in the designer.
If in code, certainly, I need to try your suggestion, Thanks!

Rajesh
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top