• No results found

Opening a table

In document Framework eBook (Page 138-142)

The USE command is used to open a table. For example:

USE Customers

Issues

The name of the table to open may contain spaces. In order to USE a table with a name containing spaces, the table name must be enclosed in quotation marks. For example:

USE "Table Name With Spaces.dbf"

116 Build Your Own Framework with Visual FoxPro

The result of issuing the previous command would result in a cursor with an Alias() of

“Table_Name_With_Spaces.” Notice that underscores have been inserted for the spaces.

The name of the table can be in one of several formats, as presented in Table 1.

Table 1. Available formats for table names.

Table Name Example

Just the table name Customer Relative path “.\Customer”

Absolute path “C:\Customer”

Universal Naming Convention \\127.0.0.1\C$\Customer.dbf or

\\Server\Share\Table

Database!Table AppData!Customer

Design considerations

The name of the table is all that is required to open a cursor. The table name can be in any one of the formats listed in Table 1 and is assigned to the CursorSource property of MyCursor.

Once opened, however, MyCursor no longer works with the value of CursorSource.

Instead, it works with the name assigned to the table as defined by its alias. This is an important distinction. As you saw with the spaces example, the name of the table is not guaranteed to be the same as the alias created for it. The developer can also choose to supply an alias if he or she desires. If none is supplied, the name of the table is used by default.

As you will see later in this chapter, in the section about adding a new record, identifying a primary key field enables MyCursor to generate a primary key value. The developer can identify the primary key field in the cPrimaryKey property. However, FoxPro enables you to query information about the table itself. In other words, you can determine the name of the primary key by using a table’s metadata. I’ll show you some methods that allow you to accomplish this after I review the code for the Open() method.

Finally, as a matter of good housekeeping, if the class opens a table, it should close the table. A test is done to determine if the class truly opened the table or if it was already open before it was called.

Here’s the Open() method.

*--MyCursor.Open() LOCAL lcTableToOpen

WITH THIS

ASSERT ! EMPTY(.CursorSource) MESSAGE "Uh...Need a table here"

IF EMPTY(.Alias)

.Alias = JustTable(ALLTRIM(.CursorSource)) .Alias= STRTRAN(ALLTRIM(.Alias),' ','_') ENDIF

.lCLoseOnExit = IIF(USED(.Alias),.F.,.T.) lcTableToOpen = ["]+ALLTRIM(.CursorSource)+["]

IF .lCLoseOnExit

USE &lcTableToOpen AGAIN ALIAS (ALLTRIM(.Alias)) IN 0 SHARED ENDIF

Chapter 9: Cursor and CursorAdapter 117

.setorder() .SetPrimaryKey()

RETURN USED( .Alias ) ENDWITH

How to use the Open() method

The table to open is specified by filling in the CursorSource property. Although you can set the value in code as shown in this example, you more likely will identify the table to open in the Class Designer at design time.

lo = CREATEOBJECT("MyCursor") lo.CursorSource = "AppCats"

lo.Open()

Related methods and functions

Notice how I didn’t have to specify the primary key or an alias in the previous example. The Open() method took care of those actions for me. The following functions and methods are related to identifying the primary key and the alias for the table.

Determining a primary key

FoxPro provides a function, Primary(), that returns a logical value indicating whether an index tag is the primary key for the table. To determine the primary key, you need to test each tag until the primary key is found.

In MyFrame, the GetPrimaryKey() function, located in GenProc.prg, is used to determine the primary key of an open table. GetPrimaryKey() returns the name of the primary key if one exists and .NULL. if the key does not exist. The function accepts an alias to search for, and if one is not provided, the currently selected Alias() is used by default. The code for

GetPrimaryKey() is shown here:

FUNCTION GetPrimaryKey()

LPARAMETERS tcAlias

LOCAL lcReturn, lnTagNo, lcAlias lcReturn=.NULL.

lcAlias = IIF( EMPTY(tcAlias), ALIAS(), tcAlias)

ASSERT VARTYPE(lcAlias)='C' ;

MESSAGE 'GetPrimKey(cAlias) accepts only a character parameter' IF ! EMPTY(lcAlias) AND USED(lcAlias)

FOR lnTagNo=1 TO TAGCOUNT(lcAlias,lcAlias) IF PRIMARY(lnTagNo,lcAlias)

118 Build Your Own Framework with Visual FoxPro

Notice that the record pointer is never moved and that the work area is never switched at any point during this function. I mentioned earlier that part of the strategy for working with a variety of buffering schemes is to make sure the framework never moves the record pointer without being specifically directed by the application developer. This function demonstrates how that concept is applied in practice.

A second function, GetPrimaryKeyValue(), also included in GenProc.prg, returns the value of a primary key. This function is not shown here.

MyCursor.SetPrimaryKey

The SetPrimaryKey() method checks to see if a value has been set for cPrimaryKey. If the name of the primary key is not provided, a custom function, GetPrimaryKey(), is called to identify the primary key for the table.

The GetPrimaryKey function defined earlier could have been called directly from the Open() method. Look at the GetPrimaryKey() function again. It is based on index tags. In some cases, a primary key may not have a tag. Free tables may not have a “primary key tag”

but certainly could have a field that uniquely identifies each record in the table. By placing the code for setting the primary key within its own method, it is easier to customize the behavior for setting the primary key without interrupting the rest of the Open() method.

MyCursor.SetPrimaryKey is a wrapper around the GetPrimaryKey() function. The code is shown here:

*--MyCursor.SetPrimarykey IF EMPTY(THIS.cPrimaryKey)

THIS.cPrimaryKey=GetPrimaryKey(THIS.Alias) ENDIF

Returning just the table

There is no single function that separates only the table name from each of the formats listed in Table 1. To determine the alias of a cursor, you must be able to separate the table name from the information provided. JustTable(), located in GenProc.prg, returns the name of a table regardless of the format used. Here is the code for JustTable().

FUNCTION JustTable() LPARAMETERS cString *--Check for data

Assert VARTYPE(cString)= 'C' and ! EMPTY(cString)

DO CASE

CASE AT('\',cString)>0 OR AT('.',cString)>0 or AT('/',cString)>0 RETURN JUSTSTEM(cString)

Chapter 9: Cursor and CursorAdapter 119

In document Framework eBook (Page 138-142)