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!

is vfp 9 can read database through network 1

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
585
PH
is vfp 9 supports opening of database through network? what is better to use if ever? cd or set path? thanks...
 
Hi Mandy_crw,

doing a SET PATH TO at the beginning of you code should always include the DB path.
This enables you to simply do a OPEN DATABASE dbname without path.

However, using a VFP DB via network, nowadays and even more in the future, isn't a go idea anymore. During the last years Microsoft has made several changes in Window's network behaviour that leads to broken db connections and therefore to corrupted tables and indizes.
Many years, this could be reverted by making small changes within the registry, but AFAIK this has become more and more difficult and (correct me if I'm wrong guys) the latest changes can't be reverted anymore.

Nevertheless, my advice is to use VFP databases on local machines and to use ODBC and SQL Server, MariaSQL, PostgreSQL, ... you name it, on remote machines in the network.


-Tom
 
I have many applications up and running where the data is accessed across a network. In fact, this is by far the most common case. I'm not aware of any specific problems this causes. But take note of what Tom says. His experience may well be more up to date than mine.

As far as CD vs SET PATH is concerned, that's quite easy to answer.

CD stands for "change directory". It does just that. It changes the default directory. So, if you open any type of file without specifying a path, VFP will look in the default directory first. Similarly, if you create a file without specifying a path, VFP will save it in the default directory.

SET PATH estabishes a list of directories where VFP will look if it fails to find a file in the default directory.

None of this has got anything to do with accessing data over a newtwork. The above applies equally to local access or accessing over a network.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Mandy,

Tom is right. but as I know a bit the nature of your application from a previous thread, I assume it's mainly a single user application and still will be. You just want multiple users to use it without needing to go to the same computer. One way to do so is to centralize data in a file share as you plan, still only let a single user start the application. In that case the network problems Tom talks about don't arise, they only arise in shared concurrent use of dbf files from multiple computer clients/workstations.

Another would be letting users connect to the single computer where it's installed via remote desktop or teamviewer or either such tools and keep the application with its local dbfs as is.

I may also misinterpret and underestimate what I know, it may only be a very small subset of the features of your application. It actually seems you did pick up the work from a previous developer as you said about yourself you're a novice but then posted a page class, something that's already involving OOP style programming and very specifically of a member class, which are two non-beginner topics at once. Even when only VFP is new to you and not OOP programming in general, the member class topic is very VFP specific. So the overall codebase might be extensive already and not your work, you only extend it.

But then that doesn't match a question about network abilities as a larger application would already work for multiple users on a network. Unless it is an application developed for single user mode, ie local dbfs of non shared data.

So, overall it would be good, if you could tell us more about the nature of your situation, whether you inherited this application code and the nature of it.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Just looking at Tom's reply in more detail. If it a choice between DBF files on a server vs a true client-server back end (such as SQL Server, MariaSQL, PostgreSQL), then I agree that there is a good argument for the latter. But there are pros and cons. Converting an existing DFB-based application to a client-server architecture is not trivial. And there are other "costs" as well.

Mandy, if that is the issue that you are asking about, then we can go into more details. But I understood that your application uses DBFs, and you were asking whether these should be stored locally or on a server. If that's the case, my earlier post still applies.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mandy,

Mike has good questions too. I still struggle a bit about whether you're just a VFP novice and not at all novice developer, started with an extensive codebase or just by chance picked up code from somewhere that's not trivial VFP, but was trivial enough to get to work and extend with some legacy VFP knowledge. Then how you came to VFP at all, as it's an old legacy outdated and unsupported language.

Also, I'm still not sure whether you really have your class defined with PRG code or it was exported by you for posting. Which again isn't trivial VFP knowledge about how to use the class browser of VFP and its viewcode-tool, which again are not things even long term VFP developers make use of at all, at least not often.

So the likelyhood is you picked this up from newsgroups or forums or download elsewhere.

I already touched the topic of how it's easier, especially for novices, to maintain code in the visual form, forms (SCX) and classes in classlibes (VCX) mean to use the visual designer, while classes based on the DEFINE CLASS in PRGs will never give you a visual representation. And within a PRG you also don't get the help the method code editor offers for forms and classes switching the code sections with it's Object /Procedure comboboxes. Or with the list of methods in the properties window or both.

Several things don't match for me here.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Just another thing to throw into the pot ....

Regardless of where you store your database, and regardless of DBF vs client-server, it nearly always makes sense to store your executable files locally. This will give you much better performance than putting them on a server (but at the cost of being a little bit harder to distribute updates).

Mandy, I know that was not the question you were asking, but it's an important point to keep in mind.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Mandy,

In addition to what has already been suggested - the first question is: What do you understand by network: a LAN having wired/WiFi access to a local NAS or a WAN needing Internet to access the data (Server, Cloud, ...)?

From my experience:

My data are on a local NAS and are accessed over a Gb wired LAN, the shared folders on the NAS are mapped as local drives - for over 10 years this has been working fine for me (first W7-Pro - now W10 and VFP9-SP3). This NAS is also configured as a WebDav server and hence allows me to access the data over the Internet - this is also working fine for me.

Beware however of (weak) WiFi - this may break data flow and corrupt files.

hth

MarK
 
NAS are a good point, as they usualy are Linux based file servers, the Micsrosoft oplocks mechanics doesn't effect you. NAS have other problems with other locks, real locks, sometimes. I also don't know how far the windows network emulation is, that's used with Linux based NAS, it usually lags behind what Windows does but finally emulates that, so also oplocks may become a part of NAS storage eventually, I'd not rely on the Linux basis keeping such problems off of you forever, but there is a good chance you get some Linux developer look into it or have much more configuration options and options to change a module (samba) to your needs, if necessary.

Bye, Olaf.

Olaf Doschke Software Engineering
 
I use both VFP dbc/dbf and remote servers for solutions. In small shops that might only have a few users (>2 and typically <10) they do not want the overhead expense of a server solution. So in these cases a dbc/dbf is used on a shared drive (I have used a drive by Buffalo that runs Linux and provides the share). In design time, I have all the tables defined as dbf inside a dbc. These are then used in the form dataenvironment in order to build the forms. But the dbc/dbf path is set to my design-time path which is different from the run-time path for the dbc/dbf. I do not use the SET PATH TO in my programs. Instead, in my main PRG program for starting the program, I read a local table for configuration information. One of the configuration settings is the DBC Path. I set this run-time path to a property value (custom on _VFP). Then in the form's data environment I implement the event method BeforeOpenTables() with the following:

Code:
=SetDBCPath(thisform.Dataenvironment, _VFP.DataPath, "<<YourDBCName>>")

This will call a custom function that changes the form's path. Below is the code:

Code:
************************************************************************************************
*
*  Routine for setting the database directory location for the form
*
FUNCTION SetDBCPath
LPARAMETERS toFormDE, tcDBCPath, tcDBCName
LOCAL lcDBCName, lcFilePath, lnNumCursors, lnNdx
LOCAL ARRAY laProperties[1]
lcDBCName  = FORCEEXT(tcDBCName, "DBC")
lcFilePath = ADDBS(tcDBCPath) + lcDBCName
lnNumCursors = AMEMBERS(laProperties, toFormDE, 2)
FOR lnNdx=1 TO lnNumCursors
	IF UPPER(LEFT(laProperties[lnNdx], 6)) = "CURSOR"
		IF ATC(lcDBCName, toFormDE.&laProperties[lnNdx]..Database) > 0
			toFormDE.&laProperties[lnNdx]..Database = lcFilePath
		ENDIF
	ENDIF
ENDFOR
ENDFUNC
 
thank you for all your answers... i was enlightened... i said i am a novice because my programming language skills are still for foxbase, when i needed to do a project i have look and searched for the internet and so i have gotten one which is coded in vfp9, so i borrowed an installer of vfp 9 and notice that it has almost desame language with foxbase with i know much... so i extended the one i got from the net, and little by little i am starting to enjoy writing codes with the use still of foxbase code... thats whay i said i am a novice... and i thank you for all your support, i am now enjoying alot because of your inputs... going back to network, i want my project (dbf) to be accessed by a remote computer to append or edit some records... i will be using wifi signal not LAN... thanks and god bless people... thanks for guiding me always...
 
The part about having a setup configuration path is what I evangelize and recommend. You can still have central control about this configuration using an application update procedure that is controlled by a current version application repository folder used as the source of the local installations.

The other part about mending the database property of DE objects on the fly is a way that's often referred to in Tamar Granor's Hacker's Guide. So it's clearly a good solution.

It's still one of those quirks that I recently mentioned, for which solutions are glorified that should actually not be necessary at all. I mean, of course we're all thankful, but any line of code mending a problem you shouldn't have can't be said to be elegantly solved. When the problem actually is that the IDE displays relative paths but actually stores full paths and thus makes DE object immovable. Usually it's worse anyway, as the difference between development and production can be just another root path, for which the same relative path would help a lot, but at development you want to profit from local drive speed configure a local root path until you may want to test with network share under real conditions.

But you can't easily switch the objects in the DE when they don't really store the relative path they actually promise to store by their display in the properties window. That forces you in that situation and is one of the reasons I say I didn't use the DE at all. You can load up data access objects in the Load event and some application frameworks do so, too.

Even with a DE usage, USE commands with a totally wrong path or also DE objects with wrong pathing can be made work without SET PATH nor CD. It's sufficient you have the DBC open and current to get at its DBFs and views. And it's helpful, therefore, though it needs specific setting about the timeout for not finding files. That's overlooked by many, as it's a very low-level detail. How fast VFP finds files then also depends on how fast it does not find them in the wrong only developer path.

You may also turn this around, as you can take that latency time as a developer. But only in situations working for a company, for example, where the final path actually is hardwired.

It's sufficient that your design time paths are not available at runtime for customers that searching the database happens. Regarding the original question whether to use SET PQATH or CD I'd also then prefer CD for a single path, but you can't cover multiple paths, that way. So this works for all external resources that have all the same path and speaks for a database storage of all files in one folder. I preferred a little structuring of directories there too. And that also works fine with CD, as long as you open DBC dbfs without path and let the currently active dbc find them. This doesn't only work when you USE dbname!tablename syntax with the explanation mark but also if you just USE tablename, a dbf is not found in the default directory and a dbf is open, the table is looked up in its meta-data about tables that are part of the dbc.

This demonstrates you can easily write code completely independent of both CD path (or same game SET DEFAULT path) and of SET PATHS search paths, as it only relies on the DBC to know its tables:
Code:
*initialiszation of dbc structure and directories
Close Tables All
Close Databases All
Cd (Getenv("temp"))

Try
   Cd dbpathsdemo
   Erase dbp*.*
   Cd Tables
   Erase dbp*.*
   Cd ..
   RmDir Tables
   Cd ..
   RmDir dbpathsdemo
Catch
   *
Endtry

Mkdir dbpathsdemo
Mkdir dbpathsdemo\Tables
Cd dbpathsdemo

Create Database dbp.Dbc
Create Table dbptable1.Dbf Name tableone (id1 int)
Create Table dbptable2.Dbf (id2 int)

Close Tables all
lcDBC = Dbc()
Close Databases all

* Application data handling
Open Database (Addbs(Getenv("temp"))+"dbpathsdemo\dbp.dbc")
Set Database To dbp

* Intentionally set defetula directory elsewhere
Cd C:* Intentionally set no paths
Set Path To

* Works with long table names
Use tableone in 0
Select tableone
? Alias(), Dbf()

* works with file names
Use dbptable2 In 0
Select dbptable2
? Alias(), Dbf()

This does not demonstrate how DE objects work, though, as the Database property you mention and handle is about dbfs of a DBC, The DE stores this information to ensure the DBC given in that property is open and set. And that's the bad part. It might be able to handle cases with multiple DBC better than a simpler strategy of just one. What the DE handling now does is look whether that DBC is open, since the path is wrong detects it's not and tries to find and open it and then finally opens the given table. All that falls flat already when not using the DE And just a series of commands or data access objects doing the file handling.

Notice the way I finally do the "Application data handling" part, the only line of code needing a path is the Open Database. And that, as you said, needs to come from configuration. That's what no solution gets around.

Last not least, you only have that problem when using a DBC. DE object of free tables have nothing in their database property and hardcode the path to the DBF. There's that problem again, but that's surely solvable with both CD or SET PATH. And as far as I assume even though I tell I'm not fully sure, this will not be more than a few DBFs, free DBFs, too.
So these are details I think Mandy will not need at all.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Mr./Mrs Ggreen61
Your function SetDBCPath(thisform.Dataenvironment, _VFP.DataPath, "<<YourDBCName>>")
_VfpDataPath ??? is that not an other way of Set('Path')
Stay healthy,
Koen
 
Koen,

here's the difference when you SET PATH TO well-knowndbcpath vs use the function going through DE objects before they open their dbf:

* Set path solution
0. (preparation step before calling form): SET PATH ... in main.prg
1. Trying to find database at wrong path
2. finding dbc at path set by SET PATH (may need further steps the more paths you set)
3. open that dbc or realize it's already open and was already used for previous dbfs as alternative to the original path

* setdbcpathfunction
0. (preparation) read dbc path from onfig, store in some property of _VFP (or _screen or goApp).
1. set database property of DE object to known location before any file finding or accessing happens.
2. Find DBC at given location, not having looked into the wrong path saving time, open that dbc or realize it's already open... (similar to step 3 of Set path solution).

In the past I already recommended both solutions at times, mine works on slightly another basis. Anyway, also not finding files in default. It's not a big performance hit unless you have a really bad configuration of timeouts regarding the file system NOT finding files. I first made notice of that with Samba (Linux) way back in 1999 or 2000. There you can dig down to such details, that are quite hidden from you in Windows.

Both solutions work, but see, the second solution is one step ahead, And yes, to gain that step you first have the cost of previously iterating all DE objects and setting their database property. The code can even be more complex, if you need to care for multiple DBCx, like one for tables, one for views separate per user. But the point is not that this takes a few more commands. Not finding a file is a process of the file system, that involves waiting for a timeout, giving time to remote resources, for example, to find a file or directory and report it back (or not). So not finding a file can take macroscopic time. That's far more time than the whole code iterating all DE objects, even if you'd run that 1000s times. Really macroscopic time, seconds, not just split seconds. It can be set low, though.

My strategy of making use of the DBC knowing paths to its dbfs both by their internal name (defaulting to their file name) is actually also making a detour of not finding the dbf file in the default directory. So it's usually okay and then also okay to SET PATH. If you don't have problems with that don't fix it. You know this can lead to finding files named the same depending on the order of Paths set via SET PATH, so you'll ensure to have unique file names and keep paths to a low number anyway.

The reason I prefer to not depend on anything is that I have usually other uses of the default directory than setting it to the database path, ie setting it to a folder with DLLs, FLLs, config files, reports not included in the EXE etc. - in short dependencies of the application. Therefore I usually have that at the location of the EXE itself.

Bye, Olaf.

Olaf Doschke Software Engineering
 
My data are on a local NAS and are accessed over a Gb wired LAN, the shared folders on the NAS are mapped as local drives - for over 10 years this has been working fine for me

Mark, one of my clients has exactly the same setup. And it's been working for even longer yours - about 15 years, I think. The client is very happy with the speed. This is the app I mentioned earlier that is using DBF fles rather than a back-end database.

You mentioned a weak wi-fi connection; this is a good point. It didn't apply in my case because, at the time that I developed the app, wi-fi was not yet a realistic proposition, so the whole network is ethernet.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Koen--

The Set('Path') gives the current setting of SET PATH TO. In my case this is empty ("") as I do not use this command. As explained very well by Olaf, I am 'hacking' the run-time path for the tables in the form's DE (I don't consider this as actual hacking since property values can be changed at run-time by the developer). The table path stored in the form's DE is fixed; I need it to be dynamic so my custom function makes the change to the property value at run-time. My application also has the ability to have offline access (when not connected to the network). So it has to be able to point the database location based on server availability; i.e., to server if available, or to local PC if server is not available.

If you add the runtime database path via the SET PATH TO command, then VFP could find the tables; I just do not use this method by choice.

As Olaf also mentioned a lot of frameworks use the form Load() event to load the tables. This is a good solution too; but you still have to have a global setting for the path (the form parameters are passed to the Init() event which is after the Load() event) for the Load() event to 'know' where to get the tables. I use the form DE as I have my own editor for the form (SCX) that gives me additional functionality for editing. I have intellisense to get the fields from the form DE for code completion when typing the table name. So I like using the DE.

Greg
 
I have an application which uses (lots of) DBF:s only at about 40 places around Sweden. All the setups are alike and have everything in a share on the "server", which sometimes is an ordinary PC. Number of users is between 2 and 10.
Unlike Mike (which I appreciate very much), I think that the performance doesn't suffer much because VFP:s cashing is so efficient. Also it gets SO much easier to upgrade the system (or moving/deleting it) when everything is in the same place.
 
All this was addressing LAN (local area network), someone already mentioned WAN as LAN extension for sites that are separated from each other and can't be in a LAN.

But to make a long story short, this is not applicable if you think of a website done with your VFP EXE. There are a few new threads about that when you want to go that route.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Olaf,
I know there is more than one way to skin a cat, still would like to have your pro and cons to the system I work with to set my environment:

Code:
Set Path To []
? SET('path')
*** Go ahead and set the path
If Version(2) # 0
	***  We are in Development Mode
	***  Set up Project search path
	m.lcPath = Home() + ';' + Fullpath( Curdir() ) + [Class;  Data; Forms; Images ; Menu; Progs ; Reports; ReportingFiles]

Else
	*** We are in Production Mode
	*** Set up application search paths
	m.lcPath = Fullpath( Curdir() ) + [ ;Reports ; ReportingFiles]
Endif

** to set my dataenvironment:
** Get value from projectsini file:
lcDataDir = goInimgr.GetValue( 'Datadirectory','DIRECTORY','PROJECTS.INI')
lcPath = Set('PATH')
lcPath = m.lcPath+ [;] +m.lcDataDir
If Version(2) # 2
[indent][/indent]? lcDataDir ** for quick reference in development mode, echo the datadir on my screen
Endif
Set Path To []
Set Path To (m.lcPath)

My advantage, as I see it: only a few line of code and just change the value in the projects.ini file to the (new) location where the .dbc is positioned and you are done
Regards,
Koen
 
I personally never used the Code to mend DE objects. So you can get my approval on one side.

On the other side, I liked what I had to use with the Mere Mortals Framework and some non-official successor if it. That was not working with DEm older than the DE class, in the latest version it did make use of Cursoradapters dynamically loaded into data environments, so that made use of the latest VFP has to offer in data access. A DE was an organizational element of multiple business objects with Cursoradapters as data access objects.

But they also didn't use the technique to set DE objects Database property. Also, we worked with SQL Server, which makes it even less relevant, but the use of DBC was foreseen in the framework, too.
The way this works with cursoradapter differs anyway, as you address your DBC and DBF source in cursoradapter datasources differently.

Quintessence is I usually work with targeting exactly the path I want to target, not just indirectly via paths set to SET PATH. That means more code to add a movable basepath where it matters to avoid hardcoded paths in code. I got best results with this strategy of having paths under my full control and still have the flexibility by configuration.

The moment I got fed up with less than full path control was when a path to local drive somewhere embedded itself in an EXE and on customers sites that dive letter often was related to a CD drive, in which case the thing I already mentioned about, the timeout for not finding files is having a macroscopic effect on not finding a file and then search along SET('PATH'). It worked very slowly when the drive had a badly readable CD before the file system answered the file was not found on CD and it even errored in case the CD drive had no medium inserted.

This led me to be the full control freak.

I know I am contradicting myself with what I praised about the DBC feature to find its DBFs without giving any path. There is a way this works more directly for you, too, ie addressing dbc!nametable, but I now also don't work with completely self-controlled code and much code I inherit opens up DBFs at data session start, sometimes with code rather than the visual DE part. Also, code acting on startup and working with datasession 1 from start of the application. When an application is single form most of the time (except a few popups).

In the end, I can't give you affirmation from the same experience you likely have with your way. As said, if it works don't break it. The reason I don't get hands on the basis of code of inherited projects, the reason I used the Mere Mortals based framework that would use DE with DBFs, but never used it with DBFs and but with an SQL Server backend... All of that means since I opted out of using the DE I never had longterm experiences with it, even where the possibility arose.

I also like to base any nonvisual classes on container, even if custom or control or date environment or page would be better specific fits. It always enables the combination of classes into each other better than any other base class. So I also didn't use DE for data access objects as base class. If MS would have enforced DE to be used for any commands related to workarea access, if it would be a real datasession base class, then I might have made more use of it.

There is a fine reason for the DE as its OOP class variant, in that you now can have a class hierarchy and finally have concrete DE class for an SCX, both at the end of a class hierarchy tree. But also in the past when I started creating a class hierarchy for in libraries, I didn't go the route of ending the tree branches on SCX forms, I used classes and OOP throughout the project. Also, something coming from the framework I used is a doform function that give you about the same comfort as do form with SCXEs does with form classes instead, caring for instantiation and showing the form, making it modal or not, etc.

And for the case it may be overlooked:
It's okay to use the path method and I'd be the last to downgrade it when you get it to work reliably for you. I like the way this works out for DBCs taking care of not found DBFs as in my sample code, so I do also have a liking for this automatic finding mode. The problem with drives with removable media is also no big deal anymore, so go for it. No need to change your ways.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top