Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

1001 Things You Wanted To Know About Visual FoxPro phần 6 pptx
PREMIUM
Số trang
50
Kích thước
701.1 KB
Định dạng
PDF
Lượt xem
700

1001 Things You Wanted To Know About Visual FoxPro phần 6 pptx

Nội dung xem thử

Mô tả chi tiết

Chapter 7: Working with Data 223

CLOSE ALL

RETURN

PROCEDURE CheckStProc

DO dummy

DO OnlyaCH07

DO OnlybCH07

If you run this program from the command line you will see that with multiple DBCs

open, calling a stored procedure which exists only in one DBC is fine.It does not matter which

DBC is current, the correct procedure is located. However, if both DBCs contain a stored

procedure that is named the same, then the setting of the DBC is vitally important since Visual

FoxPro will always search the current database first and only then will it search any other open

databases.

Finally if NO DBC is defined as current, then Visual FoxPro executes the first procedure it

finds – in this example it is always the 'dummy' procedure in the aCH07 database container.

Reversing the order in which the two DBCs are opened in the ShoStPro program changes the

result for the last test. This suggests that Visual FoxPro is maintaining an internal collection of

open databases, in which the last database to be opened is at the head of the list, and is

searched first, when no database is set as current.

How to validate a database container

Visual FoxPro provides a VALIDATE DATABASE command that will run an internal consistency

check on the currently open database. Currently (Version 6.0a) this command can ONLY be

issued from the command window and by default its results are output to the main FoxPro

screen. Attempting to use it within an application causes an error.

You can validate a database without first gaining exclusive use, but the DBC index will

not be re-built, nor will you be able to fix any errors that the process may find. With exclusive

use you may choose either to rebuild the index (a plain VALIDATE DATABASE command will do

just that) or to invoke the repair mechanism by adding the ‘RECOVER’ clause to the command.

While not very sophisticated, the recovery option at least highlights anything that VFP

feels is wrong with your DBC and offers you options to either locate or delete a missing item

and to delete or re-build missing indexes (providing that the necessary information is available

in the DBC itself). The best way to avoid problems in the DBC is to ensure you always make

changes to its tables (or views) through the DBC’s own mechanisms. Avoid actions like

building temporary indexes outside the DBC or programmatically changing view or table

definitions without first getting exclusive use of the DBC.

In short, while not exactly fragile, the DBC relies heavily on its own internal consistency

and errors (real or imagined) will inevitably cause you problems sooner or later.

How to pack a database container

The Visual FoxPro database container is, itself, a normal Visual FoxPro table in which each

row contains the stored information for one object in the database. Like all Visual FoxPro

tables, deleting a record only marks that record for deletion and the physical record is not

224 1001 Things You Always Wanted to Know About Visual FoxPro

removed from the DBC. This means, over time, that a database can get large, even though it

actually contains very few current items.

The PACK DATABASE command is the only method that you should use to clean up a DBC.

Simply opening the DBC as a table and issuing a standard PACK command is not sufficient

because the DBC maintains an internal numbering system for its objects that will not be

updated unless the PACK DATABASE command is used. Using this command requires that you

gain exclusive use to the database.

Moving a database container

We mentioned earlier in this section that the only price for gaining all the functionality that a

database container provides is a minor modification to the header of the table to include a

backlink to the DBC. This is, indeed, a trivial thing UNTIL you try to move a database

container. Then its significance can assume monstrous proportions. The reason is that Visual

FoxPro stores the relative path from the table back to the owning DBC directly in the table

header. Providing that you always keep the DBC and all of its data tables in the same directory,

all will be well because all that gets stored is the name of the database container.

However, when you have a database container that is NOT in the same directory as its

tables you are laying yourself open to potential problems. We created a table in our working

directory (C:\VFP60\CH07) and attached it to a database that resided in the C:\TEMP

directory. The backlink added to the table was:

..\..\TEMP\TESTDBC.DBC

After moving this database container to the C:\WINDOWS\TEMP directory, any attempt to

open the table resulted in a ‘cannot resolve backlink’ error and the option to either locate the

missing DBC, delete the link and free the table (with all the dire consequences for long field

names that this entails) or to cancel. Being optimists we chose to locate the database container

and were given a dialog to find it. Unfortunately having found our DBC and selected it, we

were immediately confronted with Error 110 informing us that the "File must be opened

exclusively" Not very helpful!

Fixing the backlink for a table

So what can be done? Fortunately the structure of the DBF Header is listed in the Help file (see

the "Table File Structure" topic for more details) and Visual FoxPro provides us with some

neat low level file handling functions which allow us to open a file and read and write to it at

the byte level. So we can just write in the new location for the DBC and all will be well. The

only question is where to write it?

You will see from the Help file that the size of the table header is actually determined by

the formula:

32 + ( nFields * 32) +264 bytes

Where nFields is the number of fields in the table, which we could get using FCOUNT() – if

we could only open the table! (There is also a HEADER() – a useful little function that actually

Chapter 7: Working with Data 225

tells us how big the table header is. Unfortunately it also requires that we be able to open the

table.) But if we could open the table, we wouldn’t need to fix the backlink either.

The backlink itself is held as the last 263 bytes of the table header. However, the only

certain way of getting those vital 263 bytes is to try and read the maximum possible number of

bytes that could ever be in a table header. (Trying to read beyond the end of file does not

generate an error in a low level read, it just stops at the end of file marker.) Visual FoxPro is

limited to 255 fields per record so we need, using the formula above, to read in 8,456 bytes.

This is well within the new upper limit of 16,777,184 characters per character string or

memory variable so all is well.

Fortunately the field records section of the header always ends with a string of 13 "NULL"

characters (ASCII Character 0) followed by a "Carriage Return" (ASCII Character 13). So if

we locate this string within the block we have read from the table, we will have the start of the

backlink. The following function uses this technique to read the backlink information from a

table (when only the table file name is passed) or to write a new backlink string (pass both the

file name and the new backlink):

**********************************************************************

* Program....: BackLink.prg

* Compiler...: Visual FoxPro 06.00.8492.00 for Windows

* Abstract...: Sets/Returns Backlink Information from a table

* ...........: Pass both DBF File name (including extension) only to

* ...........: to return backlink, also pass new backlink string to

* ...........: write a new backlink

**********************************************************************

LPARAMETERS tcTable, tcDBCPath

LOCAL lnParms, lnHnd, lnHdrStart, lnHdrSize, lcBackLink, lcNewLink

lnParms = PCOUNT()

*** Check that the file exists

IF ! FILE( tcTable )

ERROR "9000: Cannot locate file " + tcTable

RETURN .F.

ENDIF

*** Open the file at low level - Read Only if just reading info

lnHnd = FOPEN( tcTable, IIF( lnParms > 1, 2, 0) )

*** Check file is open

IF lnHnd > 0

*** Backlink is last 263 bytes of the header so calculate position

*** Max header size is (32 + ( 255 * 32 ) + 264) = 8456 Bytes

lcStr = FREAD( lnHnd, 8456 )

*** Field records end with 13 NULLS + "CR"

lcFieldEnd = REPLICATE( CHR(0), 13 ) + CHR(13)

lnHeaderStart = AT( lcFieldEnd, lcStr ) + 13

*** Move file pointer to header start position

FSEEK( lnHnd, lnHeaderStart )

*** Read backlink

lcBackLink = UPPER( ALLTRIM( STRTRAN( FGETS( lnHnd, 263 ), CHR(0) ) ) )

*** If we are writing a new backlink

IF lnParms > 1

*** Get the path (max 263 characters!)

tcDBCPath = LEFT(tcDBCPath,263)

*** Pad it out to the full length with NULLS

lcNewLink = PADR( ALLTRIM( LOWER( tcDBCPath ) ), 263, CHR(0) )

*** Go to start of Backlink

FSEEK( lnHnd, lnHeaderStart )

226 1001 Things You Always Wanted to Know About Visual FoxPro

*** Write the new backlink information

FWRITE( lnHnd, lcNewLink )

*** Set the new backlink as the return value

lcBackLink = tcDbcPath

ENDIF

*** Close the file

FCLOSE(lnHnd)

ELSE

ERROR "9000: Unable to open table file"

lcBackLink = ""

ENDIF

*** Return the backlink

RETURN lcBackLink

What happens to views when I move the database container?

The good news is that moving a database container has no effect on views. Views are stored as

SQL statements inside the database container and, although they reference the DBC by name,

they do not hold any path information. So there is no need to worry about them if you move a

DBC from one location to another (phew!).

Renaming a database container

Renaming a database container presents a different set of problems. This time, both tables and

views are affected. Tables will be affected because of the backlink they hold - which will end

up pointing to something that no longer exists. However, this is relatively easy to fix, as we

have already seen, and can easily be automated. In this case, though, Views will be affected

because Visual FoxPro very helpfully includes the name of the DBC as part of the query that is

stored. Here is part of the output for a query (generated by the GENDBC.PRG utility that ships

with Visual FoxPro, and which can be found in the VFP\Tools sub-directory):

FUNCTION MakeView_TESTVIEW

***************** View setup for TESTVIEW ***************

CREATE SQL VIEW "TESTVIEW" ;

AS SELECT Optutil.config, Optutil.type, Optutil.classname FROM

testdbc!optutil

DBSetProp('TESTVIEW', 'View', 'Tables', 'testdbc!optutil')

* Props for the TESTVIEW.config field.

DBSetProp('TESTVIEW.config', 'Field', 'KeyField', .T.)

DBSetProp('TESTVIEW.config', 'Field', 'Updatable', .F.)

DBSetProp('TESTVIEW.config', 'Field', 'UpdateName', 'testdbc!optutil.config')

DBSetProp('TESTVIEW.config', 'Field', 'DataType', "C(20)")

* Props for the TESTVIEW.type field.

DBSetProp('TESTVIEW.type', 'Field', 'UpdateName', 'testdbc!optutil.type')

* Props for the TESTVIEW.classname field.

DBSetProp('TESTVIEW.classname', 'Field', 'UpdateName',

'testdbc!optutil.classname')

ENDFUNC

Notice that the database container is prepended to the table name on every occasion - not

just in the actual SELECT line but also as part of each field’s "updatename" property. This is, no

Chapter 7: Working with Data 227

doubt, very helpful when working with multiple database containers but is a royal pain when

you need to rename your one and only DBC. Unfortunately we have not been able to find a

good solution to this problem. The only thing we can suggest is that if you use Views, you

should avoid renaming your DBC if at all possible.

If you absolutely must rename the DBC, then the safest solution is to run GENDBC.PRG

before you rename it and extract all of the view definitions into a separate program file that you

can then edit to update all occurrences of the old name with the new. Once you have renamed

your DBC simply delete all of the views and run your edited program to re-create them in the

newly renamed database.

Note: The SQL code to generate a view is stored in the "properties" field of each "View"

record in the database container. Although it is stored as object code, the names of fields and

tables are visible as plain text. We have seen suggestions that involve hacking this properties

field directly to replace the DBC name but cannot advocate this practice! In our testing it

proved to be a thoroughly unreliable method which more often than not rendered the view both

unusable and unable to be edited. Using GENDBC may be less glamorous, but it is a lot safer!

Managing referential integrity in Visual FoxPro

The term "referential integrity", usually just abbreviated to "RI", means ensuring that the

records contained in related tables are consistent. In other words that every child record (at any

level) has a corresponding parent, and that any action that changes the key value used to

identify a parent is reflected in all of its children. The objective is to ensure that 'orphan'

records can never get into, or be left in place in, a table.

Visual FoxPro introduced built-in RI rules in Version 3.0. They are implemented by using

the persistent relationships between tables defined in the database container and triggers on the

tables to ensure that changes to key values in tables are handled according to rules that you

define. The standard RI builder allows for three kinds of rule as follows:

• Ignore: The default setting for all actions, no RI is enforced and any update to any

table is allowed to proceed - exactly as in earlier versions of FoxPro

• Cascade: Changes to the key value in the parent table are automatically reflected in

the corresponding foreign keys in all of the child tables to maintain the relationships

• Restrict: Changes which would result in a violation of RI are prohibited

Setting up RI in Visual FoxPro is quite straightforward and the RI builder handles all of

the work for you. Figure 7.3, below, shows the set-up in progress for a simple relational

structure involving four tables (We have used the tables from the VFP Samples "TestData"

database to illustrate this section). So far the following rules have been established:

Tải ngay đi em, còn do dự, trời tối mất!