Previous Page TOC Next Page



- 20 -
Creating Front-Ends for Client/Server Databases


Up to this point, Database Developer's Guide with Visual Basic 4.0 has used desktop database files in all of the examples of Visual Basic 4.0 database applications. Sample applications that use Jet database files predominated in the preceding chapters because the .mdb file format is Microsoft's (and the author's) preferred database file structure for applications that do not need to maintain interoperability with existing applications that share dBASE, FoxPro, or Paradox table files. Another reason for using the .mdb database file structure is that .mdb files resemble the file structures used by client/server databases.

This chapter introduces you to the principles employed to create Visual Basic 4.0 database applications that serve as front-ends to client/server RDBMS back-ends. The RDBMS used for the majority of the examples in this chapter is Microsoft SQL Server versions 4.21a and 6.0 (SQL Server) running as a service of Windows NT Server 3.51. SQL Server 6.0 is one of the components of Microsoft Back Office 1.5, the version that was current when this edition was written. SQL Server 6.5, which offers a variety of new features for enterprise computing, is scheduled for release in mid-1996. All versions of SQL Server are backwardly-compatible with version 4.21a and can be accessed through Jet 1.x, 2.x with 16-bit ODBC drivers, and via Jet 3.0 with 32-bit ODBC drivers.

The examples in this chapter use the 32-bit Microsoft ODBC API (version 2.5), so the examples are equally applicable to most client/server RDBMSs for which 32-bit ODBC drivers that support core-level SQL grammar and offer level 2 ODBC compliance are available. The preceding chapter, "Using the Open Database Connectivity API," describes Visual Basic 4.0's interface to the ODBC API in detail and explains how to use single-tier ODBC drivers. Therefore, this chapter discusses only those elements of the ODBC API, such as creating client/server ODBC data sources that are specific to multiple-tier ODBC drivers and Visual Basic 4.0 front-ends for client/server RDBMSs. This chapter includes an example of exporting data from Jet databases to client/server tables because Visual Basic 4.0 developers often are called on to upgrade Visual Basic and Access applications from desktop RDBMSs to client/server database front-ends.

Designing Visual Basic 4.0 front-ends for client/server databases follows the same methodology as designing applications that manipulate tables of conventional desktop databases, as described in preceding chapters. If you have an RDBMS table structure that duplicates the structure of the tables that compose your desktop database, you simply create an ODBC data source and link the tables from the server database to a local .mdb file. (Link replaces attach in Jet 3.0 terminology.) Jet 3.0 automatically handles all of the remote access issues for you and lets you use bound controls to display and update table data. Alternatively, you can apply the OpenDatabase method and the OpenRecordset method to create a Recordset object of the Dynaset or Snapshot type to manipulate a query result set. (The Table-type Recordset isn't available with client/server RDBMSs.) You can elect to bypass Jet 3.0 and let the server process the query by invoking the Execute method with the dbSQLPassThrough option to create a Recordset object of the Snapshot type. This chapter describes techniques for all three methods of manipulating data in tables of client/server RDBMSs.

The examples in this chapter use Microsoft Access 95 to export files to an SQL Server database and to link SQL Server tables to a Jet 3.0 database. It's possible to use VBA code and SQL CREATE TABLE statements to create server tables and INSERT INTO statements to export data to the tables. You also can use Visual Basic's Data Manager add-in, the VisData sample application, or TableDef operations in VBA code to link tables to a Jet .mdb file. All versions of Access provide automated exporting of table structures and data to client/server RDBMS, as well as offer a quick and simple linking of the tables to a new .mdb file. If you intend to develop client/server front-end applications using local .mdb files for subsequent "upsizing" to a client/server RDBMS, Access is an indispensable tool for making the transition.

Using Microsoft SQL Server


Microsoft's objective for its BackOffice software suite is to gain market share in the "enterprise computing" sector, which today is dominated by mainframes, minicomputers, and high-end PC servers running UNIX. Microsoft has established an aggressive price structure for BackOffice and its components; the licensing cost for SQL Server is substantially less than competitive RDBMSs offering similar performance and features. Installation and administration of Windows NT 3.51 and SQL Server 6.0 is far simpler than that of UNIX and UNIX-based RDBMSs. Therefore, many smaller firms, which traditionally have employed shared file systems for multiuser database systems, are moving to client/server systems. The practical limit for shared-file desktop database systems is 20 to 50 simultaneous users, depending on the ratio of decision-support to online transaction-processing applications in use. Migration from shared-file to client/server systems has created a substantial demand for Visual Basic developers with client/server credentials. It's a reasonably sure bet that the majority of new Visual Basic 4.0 client/server front-ends will use Microsoft SQL Server as the back-end. The sections that follow describe the most important features of SQL Server.

Networking Features of SQL Server


You can connect to SQL Server via NetBEUI, IPX/SPX, TCP/IP, and a variety of other network protocols. NetBEUI (the Windows Network protocol) often is used for new server installations at smaller firms because of its speed and simplicity. Many shared-file database systems run over NetBEUI because the default protocol for Windows for Workgroups 3.1+ is NetBEUI. NetWare IPX/SPX protocol most commonly is used where Novell networks predate installation of Windows NT Server and SQL Server. The current trend is toward TCP/IP as the favored protocol for client/server networking because of its support of heterogeneous networks, which are likely to include servers running NetWare, UNIX, and Windows NT. Use by the Internet also has contributed to the general acceptance of TCP/IP as the primary networking protocol for at least the last half of this decade. Microsoft calls TCP/IP its "strategic protocol for scaleable Windows-based networking."

The networking features of SQL Server are designed for maximum user convenience; for example, you can set up Windows NT so that users are automatically logged on to SQL Server when they log on to the network. Automatic logon to the database server also is provided across remote servers in Windows NT domains that share a trust relationship. Successive versions of SQL Server have demonstrated substantial improvements in performance with increasing numbers of simultaneous users The database objects of SQL Server 6.0+ are compatible with those of SQL Server 4.2+, so upgrading to newer versions is a relatively painless process.

SQL Server 4.21a for Windows NT and later versions of SQL Server use one or more Net-Libraries to provide access by a variety of networked clients. SQL Server simultaneously supports named pipes connections over NetBEUI, TCP/IP, and IPX/SPX, and uses the TCP/IP sockets API for communication with Macintosh, UNIX, and DEC MVS clients. Windows 3.1+ clients use a 16-bit library (DBNMP3.DLL) to implement named pipes; Windows 95 and Windows NT use a 32-bit named pipes library (Dbnmpntw.dll) on the client side.

Connections, Threads, and Symmetrical Multiprocessing


A conversation between an application and SQL Server takes place through one or more connections established by the named pipes service or by one of the other Net-Libraries supported by SQL Server. A connection is similar in concept to that of the Windows Sockets for TCP/IP communication. Each open connection is dedicated to the client workstation that originated the connection and may persist for a period of time after the client is finished using the connection.



The following information relating to the Jet 2.0 database engine's use of SQL Server connections is based on the Microsoft "Jet Database Engine ODBC Connectivity White Paper," dated November 15, 1993, by Neil Black of Microsoft's Jet Program Management group and Stephen Hecht of the Jet Development group. You can download this white paper in Word format (Rjetwpv2.doc) as RJETV2.ZIP from the ODBC/Client/Server Library of the MSACCESS Forum on CompuServe. If you use or intend to use Visual Basic 4.0 front-ends for SQL Server databases, you need a copy of this white paper to understand fully how the Jet database engine manages connections. Connection management by Jet 3.0 is quite similar to that of Jet 1.1 and 2.x.

When you use the Jet database engine to connect to a server back-end with the ODBC API and create a Recordset object of the Dynaset type from a query, the operation usually requires at least two connections. (One connection obtains information about the query from the server and the other passes the data to your application.) Recordset objects of the Dynaset type having less than 100 records and Snapshot-type Recordset objects require only a single connection. If your query is based on a complex SQL statement that involves multiple JOINs, many GROUP BYs, or creates a crosstab query, it is likely that your application will open three connections at once. Although the Jet database engine attempts to share connections when it can, there are many situations in which several simultaneous connections may be required by your application. Each user connection requires about 18KB of server memory; on installation, 25 is the default maximum number of SQL Server connections and is likely to support 10 simultaneous users. You must increase the maximum number of SQL Server connections as workstations running SQL Server front-ends are added to the network.

Both Windows 95 and Windows NT are multithreaded operating systems. A thread is a single task that is executed by an application or the operating system. Multithreaded operating systems enable multiple tasks to appear to run simultaneously; the operating system determines the priority of the task and enables tasks with the highest priority to execute first and most often. Tasks with higher priorities can suspend processing of lower priority tasks; operating systems that enable task priorities to govern the flow of the execution of tasks are called preemptive multitasking applications. 32-bit applications must be coded explicitly to support multiple threads of execution. SQL Server and Access 95 are multithreaded 32-bit applications; Jet 3.0 supports up to three threads of execution.

Windows NT provides a thread for each connection to SQL Server from a worker pool of threads whose population is set by the sp_conFigure stored procedure. When a client workstation makes a request from SQL Server, one of the threads from the worker pool is assigned to the workstation's connection. When the request is fulfilled and the connection is terminated, the connection thread is returned to the pool. If a client workstation requests a thread and none are available in the pool, the first thread released by another connection is assigned to the request. When a fault occurs during execution of a thread, only the connection associated with the thread is affected. Thus, a page fault on a single connection does not bring down the server.

The advantages of a multithreaded operation are particularly evident when you add more than one microprocessor unit to the server. Windows NT supports thread-level multiprocessing, usually called symmetrical multiprocessing (SMP), and is referred to as a scalable operating system. These terms mean that multiple processors that share the same memory region can execute any thread. This process also is called symmetrical load balancing. If a thread is executing on a processor that is running near capacity, the thread can be transferred so that it executes on another processor. Windows NT 3.51, and thus SQL Server, supports up to eight Intel processors. Therefore, it is unlikely that a Windows NT server running on SMP hardware would ever become CPU-bound if enough sockets are available to hold additional processors. Multithreaded SMP operation and the capability to run on a variety of RISC microprocessors, not just members of the Intel 80x86 series, are the two most distinguishing features of Windows NT.



SQL Server 6.0 provides "100 percent scalability" for up to four processors; therefore, a four-processor server theoretically has four times the capacity of a single-processor server. With more than four processors, the benefits to SQL Server of SMP begin to drop off. As an example, Microsoft says four to eight processors provide "80 percent scalability." Today's most common SMP server configurations for Intel chips use two- or four-processor motherboards.


Creating ODBC Data Sources for Client/Server Databases


Examples in preceding chapters explain the procedure for creating ODBC data sources for desktop databases using the ODBC database drivers included with Microsoft Office 95. The procedure described in the following section for adding the northwind SQL Server database as a 32-bit ODBC 2.5 data source is typical of the method of adding a data source from the majority of popular client/server RDBMSs for which 32-bit ODBC drivers are available. Each supplier has a slightly different approach to the design and collection of control objects in the dialogs used to set RDBMS-specific options for the data source.



Use of all lowercase letters for the names of database objects, including table and field names, is a UNIX tradition. Similarly, it has been a standard practice to install SQL Server with UNIX case-sensitive object names. The default installation option for SQL Server 4.21 is case-sensitive object names; subsequent versions default to case-insensitivity. It is strongly recommended that you install SQL Server using case-insensitive object names.

The two sections that follow describe how to add the northwind database as an SQL data source and how to test the validity of your new ODBC data source with the VisData sample application. You or the database administrator must add the northwind database using the SQL Server tools appropriate for your version of SQL Server. The database tables, which are derived from the Northwind.mdb sample database of Access 95, require about 2MB. Setting a database size of 3MB to 5MB for northwind provides sufficient room for adding indexes to the tables and experimenting with action queries that add a large number of records to the tables.

Adding the northwind Database as an ODBC Data Source


To use the SQL Server ODBC database driver to add the northwind database as an ODBC data source, follow these steps:

  1. Launch the 32-bit ODBC Administrator from Control Panel.

  2. Click the Add button of the Data Sources dialog to display the Add Data Source dialog.

  3. Select SQL Server from the Installed ODBC Drivers list (as shown in Figure 20.1) and click the OK button to display the ODBC SQL Server Setup dialog.

    Figure 20.1. The 32-bit ODBC Administrator application's Add Data Source dialog.

  4. Click the Options button to expand the ODBC SQL Server Setup dialog and type Northwind in the Data Source Name text box. Add an optional description in the Description text box.

  5. Open the Server combo box and select the server for the northwind database. If no entries appear in the Server combo box list, type the server name in the combo box's text component. Accept the (Default) entries for the Network Address and Network library if you are using NetBEUI (the default) as your network protocol.

  6. Type northwind in the Database Name text box and select (Default) in the Language Name combo box, as shown in Figure 20.2.

    Figure 20.2. Completing the entries to create a northwind ODBC data source.

  7. Click the OK button to close the ODBC SQL Server Setup dialog. Your new data source appears in the Data Sources dialog, as illustrated by Figure 20.3.

    Figure 20.3. The Data Sources dialog with the new Northwind data source added.

  8. Click the Close button of the Data Sources dialog to return to Control Panel.

You can verify the settings for the new ODBC data source by launching RegEdit and inspecting the \HKEY_CURRENT_USER\Software\ODBC\ODBC.INI\Northwind hive (see Figure 20.4).

Figure 20.4. Entries for the Northwind ODBC data source in the Windows 95 Registry.



The ODBC data source created in the preceding steps is available only to the current Windows 95 or Windows NT user. You can create a System data source that is available to all users of the computer by clicking the System DSN button of the ODBC Data Sources dialog to display the System Data Sources (Driver) dialog. Follow preceding steps 2 through 8 to create the system data source. System Data Sources appear in the HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI folder.


Exporting Tables from Access 95 to the ODBC Data Source


As noted earlier in this chapter, using any version of Access to export data from desktop databases to SQL Server is easier (and usually faster) than the alternatives, such as executing SQL DDL statements from Visual Basic or using SQL Server's bulk copy process (BCP). This section describes how to use Access 95 to automatically create server table structures and append records to the tables. The process described in this section also is applicable, with only minor modifications, to other SQL RDBMSs for which you have 32-bit drivers, as well as to Access versions 1.1 and 2.0.

To create tables in the SQL Server northwind database from the Access 95 sample database, Northwind.mdb, follow these steps:

  1. Launch Access 95 and open the Northwind.mdb sample database and select the Categories table in the Database window.

  2. Choose File | Save As/Export to display the Save As dialog. With the To an External File or Database option selected, click the OK button to display the Save Table 'TableName' In dialog.

  3. Open the Save as Type list and select ODBC Databases() (see Figure 20.5) to open the Export dialog (see Figure 20.6). You can change the name of the destination table in the Export Categories To text box. Click the OK button to display the SQL Data Sources dialog.

    Figure 20.5. Selecting an ODBC data source in the Save as Type list of Access 95's Save As dialog.

    Figure 20.6. Confirming the name of the SQL Server table in the Export dialog.

  4. Select Northwind from the Select Data Source list (see Figure 20.7) and click the OK button to display the SQL Server Login dialog. Click the Options button to expand the dialog.

    Figure 20.7. The SQL Server Login dialog expanded by clicking the Options button.

  5. Enter your SQL Server login ID and password in the respective text boxes (see Figure 20.8) and click the OK button to export the table to the northwind database. (This step is not necessary if you use the integrated security features of Windows NT and SQL Server.) The time required to export the tables depends primarily on the number of records in the table.

    Figure 20.8. Entering your login ID and password to open a connection to SQL Server.

  6. Select each of the unexported tables of Northwind.mdb in Access 95's Database window and repeat steps 2 through 5.



Access only exports the table structures and data; the process does not generate indexes on or relationships between tables. If you use the Microsoft Access Upsizing Wizard add-in, the Wizard automatically adds indexes and the triggers or SQL DDL statements necessary to maintain data consistency (by constraints) and referential integrity (by relations). Triggers are a type of stored procedure analogous to a Visual Basic event handling subprocedure. The trigger procedure is executed on one or more events, such as inserting, updating, or deleting a record. When this edition was written, the Access Upsizing Wizard was available from Microsoft (at a nominal charge) only for Access 2.0 and was designed to support SQL Server 4.21a and earlier versions. Microsoft is expected to release in mid-1996 the 32-bit Upsizing Wizard for Access 95, which will support SQL Server versions 4.2 through 6.5. Microsoft SQL Server 6.5 was in the beta-testing stage when this edition was written.



If the tables you are exporting have more than 10,000 rows, it usually is faster to export the table data to an .asc, .txt, or .csv file and then use the server's BCP application to import the data to the tables. In this case, export only the existing table structures to a new Access .mdb file, then use BCP to append the data from the .txt file.


Using Visual Basic 4.0's RegisterDatabase Method


[VB4_NEW]The RegisterDatabase method of the DBEngine object lets you create a statement that performs the same function as making the entries in the ODBC setup dialog, such as the ODBC SQL Server Setup dialog shown in Figure 20.3. The RegisterDatabase method, which replaces Visual Basic 3.0's RegisterDatabase statement, can be used to create or modify ODBC data source entries in ODBC.INI and the ODBC.INI hive of the Registry, identical to that which you create with the ODBC Administrator's setup procedure. Your code needs to apply the RegisterDatabase method before invoking the OpenDatabase method that refers to the ODBC data source that has been created or modified by the RegisterDatabase method.

The syntax of the RegisterDatabase method is as follows:




DBEngine.RegisterDatabase strDSN, strDriver, fSilent, strAttribs

The strDSN argument is the data source name, and strDriver specifies the registered name of the ODBC driver used with the data source. The fSilent flag determines if the driver dialogs appear when the RegisterDatabase method is invoked. (Set fSilent False to display the dialogs.) The strAttribs argument provides additional information required by the driver to make the connection. Each attribute is separated from the preceding attribute by a carriage return (Chr$(13)). To apply the RegisterDatabase method to duplicate the entries in ODBC.INI that are shown earlier in the chapter and which open the Database object, dbNwind, created from the northwind data source, use the following code:




Dim dbNwind As Database



Dim strDSN As String



Dim strDriver As String



Dim fSilent As Boolean



Dim strAttribs As String



strDSN = "northwind"



strDriver = "d:\Win95\System\sqlsrv32.dll"



fSilent = True



strAttribs = "Description=Northwind Sample Database" & Chr$(13)



strAttribs = strAttribs & "Server=OAKLEAF0" & Chr$(13)



strAttribs = strAttribs & "ODBCDatabase=northwind" & Chr$(13)



strAttribs = strAttribs & "OemToAnsi=No" & Chr$(13)



strAttribs = strAttribs & "LastUser=sa" & Chr$(13)



DBEngine.RegisterDatabase strDSN, strDriver, fSilent, strAttribs



Set dbNwind = Workspaces(0).OpenDatabase(strDSN, False, _



   False, "ODBC;")

If any of the values in the strAttribs argument do not match current entries in the ODBC.INI Registry hive for the data source, the existing entries are updated. Attribute values are not case-sensitive. The Set statement is required only if you intend to use VBA code to manipulate the data source. Once you've created the object variable of the Database type, you can treat the database as if it were a local database. The one exception is that you can't open a Recordset of the Table type over a table of a remote database.

Working with Linked SQL Server Tables


Microsoft recommends that applications requiring access to client/server databases link the tables to a Jet .mdb file. This recommendation is appropriate for prototype front-ends and relatively simple production decision-support applications. The sections that follow describe how to link client/server tables to a Jet 3.0 .mdb file, how to use the VisData sample application with linked tables, and how to create applications to compare the performance of local and remote data sources with bound controls.

Linking SQL Server Tables to a Jet Database


Linking server database tables to a Jet database is the fastest method of verifying that the export operation succeeded and that all of the tables reside in the northwind SQL Server database. You automatically generate the equivalent of a temporary local primary key index on the linked tables when you create the links. Using Access to link the tables and to generate the local indexes is much faster than writing the VBA code to accomplish this objective.

To link the tables of the SQL Server northwind database to a new version of Northwind.mdb, follow these steps:

  1. Launch Access 95, if necessary, and create a new database file, Northwind.mdb, in your \VB4 folder.

  2. Choose File | Get External Data | Link Tables to open the Link dialog. Select ODBC Databases() in the Files of Type list (see Figure 20.9) to open the SQL Data Sources dialog.

    Figure 20.9. Selecting the ODBC data source in Access 95's Link dialog.

  3. Select Northwind from the Select Data Sources list to display the SQL Server Login dialog. Enter your login ID and password, then click the OK button to display the Link Tables dialog (see Figure 20.10). Note that "dbo" precedes each table name and the space in the Order Details table name is replaced by an underscore. The "dbo" prefix refers to "database owner." Spaces and punctuation are not allowed in SQL Server object names.

    Figure 20.10. The Link Tables dialog displaying SQL Server's table names for the northwind database.

  4. Click the Select All button and mark the Save Password check box to cache your login ID and password in the new .mdb file. Saving these values eliminates the login step when subsequently opening the database. Click the OK button to begin the linking process.

  5. To make linked tables updatable, a unique index on the primary key field(s) of each table is required. Because you have not added indexes to the tables of the northwind database, Access requests that you specify the name of the field(s) that would comprise the primary key for each of the tables. Select the key field name(s) in the Select Unique Record Indentifier dialog, as shown in Figure 20.11. The key field in each table, except the dbo.Order_Details table, is the first field in the list; the dbo.Order_Details table uses a composite unique record identifier consisting of the OrderID and ProductID fields.

    Figure 20.11. Selecting the key field(s) that are used by Jet 2.x and 3.0 to identify records uniquely.

  6. After specifying the key field(s) for each table, your linked tables appear in Access 95's Database window as shown in Figure 20.12. The dot separator between "dbo" and the table name, which is illegal for Jet table names, is replaced with an underscore.

    Figure 20.12. SQL Server table names created by the Access table export operation.

  7. To maintain table name consistency with the original version of Northwind.mdb, you need to rename each table. Right-click each table name in the Database window and select Rename from the pop-up menu. Delete the "dbo_" prefix of each table and replace the underscore in Order_Details with a space. Figure 20.13 shows the result of creating aliases for each of the linked tables.

    Figure 20.13. Using local table name aliases to maintain compatibility with existing applications.

  8. Verify that Access has created a local index for the tables by selecting the Order Details table and clicking the Design button. Click Yes when asked if you want to open the table, then click the Indexes button to display the Indexes dialog. The unique record identifier (similar to a primary key) that Access creates is identified by the name "__uniqueindex," as shown in Figure 20.14. Close the Indexes dialog.

    Figure 20.14. Verifying the creation of a local index on the primary key field(s) to identify each record uniquely.

  9. Verify that the linked tables are updatable in Access 95 by clicking the Datasheet button to open the table in Datasheet view. If the tentative append button (with the asterisk) is enabled, the table is updatable.



It is a common practice among database administrators (DBAs) to provide users with SQL VIEWs of tables or query result sets, rather than direct access to the tables. Jet lets you link VIEWs in the same manner as TABLEs. (As noted in Table 19.5 of the preceding chapter, TABLE, VIEW, SYSTEM TABLE, ALIAS, and SYNONYM are Jet's default linkable objects). Traditionally, VIEWs have not been updatable; most client/server RDBMSs now provide updatable views. Even if the table(s) underlying an updatable VIEW have primary key indexes, the VIEW is not indexed. If the VIEW includes field(s) that uniquely identify its records, you can add a "fake" index when you link the VIEW to a Jet table.


Using VisData with Linked SQL Server Tables


The VisData sample application is useful to confirm the properties of linked client/server tables, as well as to inspect the ODBC connect strings that the Access linking procedure generated in order to create the links. Follow these steps to use VisData with Jet databases containing tables linked from ODBC data sources:

  1. If you have compiled the 32-bit version of the VisData sample application, launch VisData from wherever you put its icon. Otherwise, launch 32-bit Visual Basic, if necessary, and run the VisData application.

  2. Choose File | Open Database | Jet Engine MDB and open Northwind.mdb. Select the Order Details -> ODBC table in the Tables/Queries and click the Open button to display the table in the default DBGrid view. Use the vertical scrollbar to position the record pointer on the tentative append record to verify that the DBGrid control recognizes the table as updatable. (See Figure 20.15.)

    Figure 20.15. Verifying the updatability of a linked server table by checking for the presence of the tentative append record.

  3. Choose Jet | Attachments to open the Attachments window. (VisData doesn't use Jet 3.0's linkage terminology.) The ODBC connect string for each of the tables of the northwind database appears in Figure 20.16.

    Figure 20.16. Viewing the ODBC connect strings for linked server tables.

  4. Close the Attachments window and click the Design button of the Tables/Queries window to open the Table Structure dialog (see Figure 20.17). The only property of a linked table you can alter is the table name (alias). You cannot delete the __uniqueindex index, despite the fact that the index is a local object created by Jet.

Figure 20.17. Using VisData to display the properties of a table linked by ODBC.



Assigning valid user ID (UID) and password (PWD) values in design mode breaches database security. A better practice is to design a logon form in which the user enters his or her password and login ID prior to opening the first form that uses the linked tables.


Comparing the Performance of Local and Remote Recordset Objects


You can compare the speed of traversing local and remote Recordset objects of the Dynaset and Snapshot type by creating a form with two Data and DBGrid controls, as illustrated by Figure 20.18. (The term remote often is used as a synonym for a server table accessed through the ODBC API.) The first (local) Data control and its bound DBGrid uses Access 95's Northwind.mdb sample database and the second Data control/DBGrid combination uses the Northwind.mdb with tables linked from the SQL Server northwind database. Both Data controls use the Order Details table for the RecordSource property because Order Details contains a sufficient number of records (2,155) to demonstrate the difference in performance between local and remote Recordsets underlying bound controls.

Figure 20.18. A form with local and remote Data and DBGrid controls to compare performance.



The form shown in Figure 20.18 is included in the Loc_rem.vbp project in the \DDG_VB4\32_bit\Chaptr20 folder of the accompanying CD-ROM. Change the values of the DatabaseName property of both Data controls to point to the location of the native and linked versions of Northwind.mdb on your computer.

The following list describes the differences in behavior of local and remote DBGrid controls bound to Data controls whose RecordsetType property value is set to Dynaset:

The following list describes the local and remote performance differences you encounter when the value of the RecordsetType property of the Data control is set to Snapshot instead of to Dynaset:

As a rule of thumb, it's faster to work with Snapshot-type Recordsets if the number of rows is about 100 or less and the Recordset contains only a few columns. Therefore, Snapshot-type Recordsets usually are preferred for populating bound list boxes or combo boxes.



To maximize performance, especially with remote data sources, specify in the SQL SELECT statement for the RecordSource property of the Data control only the columns (fields) you want to display or bind to the control. Connecting to a table or executing SELECT * FROM TableName may return a large amount of data you don't need.


Using a Combo Box Picklist to Test Remote Database Performance


The majority of client/server front-end applications are used for decision-support purposes. A typical example of a decision-support application is a front-end for checking the status of customer orders in response to telephone inquiries. Figure 20.19 shows a simple front-end for displaying orders placed by a customer whose name you pick from a bound combo box. The latest orders of the selected customer appear first in one DBGrid control. The line items appear in a second DBGrid control when you click the record selector for a particular order.

Figure 20.19. A simple front-end application for decision support that uses bound controls.

The application of Figure 20.19 emulates real-world decision support forms that are designed to return a manageable set of records. The three Data controls are bound to Snapshot-type Recordsets for the following reasons:

[VB_NEW]The application of Figure 20.19 takes full advantage of Visual Basic 4.0's capability to change the values of Recordset-related properties of Data controls in code. The Local and Remote command buttons at the bottom of the form change the database to which the controls are bound from the local to the remote version of Northwind.mdb. The capability to quickly switch change data sources lets you evaluate the relative performance of a local and remote data source. The code to implement the application of Figure 20.19 appears in Listing 20.1. The SQL statements that populate the DBGrid controls are broken into multiple lines for readability. (You can't use VBA's code continuation pair to break literal strings.)

Listing 20.1. Code to display customer orders and select a local or remote data source.




Private Sub dbcCustomers_Change()



  'Find latest orders for CustomerID picked in combo box



   Dim strSQL As String



   strSQL = "SELECT OrderID, OrderDate AS Ordered, "



   strSQL = strSQL & "ShippedDate AS Shipped FROM Orders "



   strSQL = strSQL & "WHERE CustomerID = '"



   strSQL = strSQL & dbcCustomers.BoundText



   strSQL = strSQL & "' ORDER BY OrderDate DESC"



   dtcOrders.RecordSource = strSQL



   dtcOrders.Refresh



End Sub



Private Sub dtcOrders_Reposition()



  'Find detail records for order number clicked in grid



   Dim strSQL As String



   strSQL = "SELECT [Order Details].Quantity AS Quan, "



   strSQL = strSQL & "Products.ProductName AS Product, "



   strSQL = strSQL & "[Order Details].UnitPrice AS Price "



   strSQL = strSQL & "FROM [Order Details], Products "



   strSQL = strSQL & "WHERE OrderID = " & dtcOrders.Recordset(0)



   strSQL = strSQL & " AND Products.ProductID = "



   strSQL = strSQL & "[Order Details].ProductID"



   dtcOrderDetails.RecordSource = strSQL



   dtcOrderDetails.Refresh



End Sub



Private Sub cmdLocal_Click()



  'Set database name to local .mdb file



   Call SetDBName("E:\MSOffice\Access\Samples\Northwind.mdb")



End Sub



Private Sub cmdRemote_Click()



  'Set database name to .mdb file with linked remote tables



   Call SetDBName("E:\VB4\Northwind.mdb")



End Sub



Private Sub SetDBName(strDBN As String)



  'Change DatabaseName property value of each data control



   dtcOrders.DatabaseName = strDBN



   dtcOrderDetails.DatabaseName = strDBN



   dtcCustomers.Refresh



   dtcOrders.Refresh



   dtcOrderDetails.Refresh



End Sub

The SQL SELECT queries that populate the three bound controls return only the columns needed for display and record selection. The CustomerName column populates the combo box and the bound CustomerID column is used to select the orders displayed in the first DBGrid control. Only three columns are needed to populate the two DBGrid controls. The first time you select a customer and order, there is a brief delay when using the remote data source. Once the data for the snapshots is cached locally, the difference in application performance using a local or remote data source is almost indistinguishable.



The application of Figure 20.19 is included on the accompanying CD-ROM as PickList.vbp in the \DDG_VB4\32_bit\Chaptr20 directory. Change the value of the DatabaseName property of the bound controls and the arguments passed to the SetDBName procedure to match the location of the local and remote versions of Northwind.mdb on your computer. The SQL statement that appears in the RecordSource property of dtcOrderDetails is used to generate a design-time field list. The field list is needed in order to use the properties sheet of the DBGrid control to set the format of the Price column to Currency. Unlike Access's datasheet, the DBGrid control does not automatically format with dollar signs and trailing zeroes columns of the Currency field data type.


Connecting Directly to an ODBC Data Source


You can connect directly to an ODBC data source as an alternative to linking the remote tables to a local Jet .mdb database. Using a direct ODBC connection does not result in measurably improved performance and you can't take advantage of local "fake" Jet indexes to make unindexed server tables updatable. (Unindexed server tables are uncommon, however, so the need for local "fake" indexes seldom is necessary.) You also can't take advantage of the capability to alias linked table names.

Testing a Direct Connection to an ODBC Data Source with VisData


To test your Northwind SQL Server ODBC data source with 32-bit VisData, follow these steps:

  1. If you have compiled the 32-bit version of the VisData sample application, launch VisData from wherever you put its icon. Otherwise, launch Visual Basic, if necessary, and run the VisData application.

  2. Choose File | Open Database | ODBC to display the Open ODBC Datasource dialog.

  3. Select Northwind from the Datasource combo box. Entries in the Northwind hive of the ODBC.INI section of the Registry fill in the Database (Database=nwind) and User ID (LastUser=sa) text boxes for you, as illustrated by Figure 20.20. Leave the password blank and click the Open button to create a connection to the northwind database. (Enter your user ID and password for SQL Server if you are using an account other than the default system administrator account.)

    Figure 20.20. VisData's Open ODBC Datasource dialog for 32-bit ODBC data sources.

  4. After a short period, while VisData displays a message that reads Refreshing Table List. Please Wait. . ., a list of all of the tables in the northwind database appears in VisData's Tables window, as shown to the right in Figure 20.21. Observe that NOTE: Use of Attached Tables is the Recommended Method appears in the status bar at the bottom of VisData's window. Select the dbo.Order_Details table and click the Open button to display the table's contents. Move to the last record in the table to verify that the Recordset is not updatable because of the lack of an unique index to identify each record.

    Figure 20.21. The list of user tables in the northwind database and a DBGrid view of the dbo.Order_Details table.

  5. With the dbo.Order_Details table selected, click the Design button to display the Table Structure dialog shown in Figure 20.22. Select the UnitPrice field to verify that the ODBC driver correctly converts SQL Server's money field data type to Jet's Currency data type. (Field data type verification is necessary because the DBGrid control shown in Figure 20.21 is not automatically formatted.)

    Figure 20.22. Verifying conversion of SQL Server's money field data type to Jet's Currency field data type by the SQL Server ODBC driver.

  6. Click the Close button of the Table Structure dialog to return to VisData's main window; then close VisData.


Adding an Index to an SQL Server Table with the SQL Object Manager


When you use Access to export a Jet table to a client/server database, Jets does not create indexes on the remote table. You need to use the SQL CREATE INDEX statement or use the SQL Server administrative tools to manually add indexes to the client/server table. You can add one clustered or as many non-clustered indexes as you want to a table with SQL Server 4.2+'s SQL Object Manager or SQL Server 6.x's SQL Enterprise Manager. (SQL Object Manager and SQL Administrator also work with SQL Server 6.x.) Clustered indexes, which physically place the pages of the table in the index order, greatly improve the performance of SQL Server databases. However, you gain only a performance improvement with a clustered index if you specify that the index must be unique. (Clustered indexes are not unique by default.)

To use SQL Object Manager to create a clustered primary key index on the Order_Details table or any other table in an SQL Server database, follow these steps:

  1. Launch SQL Object Manager, connect to SQL server, and select the northwind database from the Current Database list.

  2. Click the Objects button to display the list of tables in the northwind database and select the Order_Details table (see Figure 20.23.)

    Figure 20.23. Selecting the SQL Server table to which to add an index.

  3. Choose Manage | Indexes to display the Manage Indexes dialog for a new index.

  4. Click the New button to display the Specify new index name dialog. Enter a name for the index in the New index name text box (as illustrated in Figure 20.24) and click the OK button to return to the Manage Indexes dialog.

    Figure 20.24. Specifying the name of an index to be added to an SQL Server table.

  5. In this case, you are creating an index on the primary key, so click the Clustered and Unique cells. Then choose the field(s) you want to index to create the primary key in the cells corresponding to the field names, as shown in Figure 20.25. For the Order_Details table, the OrderID and ProductID fields comprise the composite primary key.

    Figure 20.25. Specifying the properties of an index on an SQL Server table.

  6. Click the Create button to display the Create new index? dialog, as shown in Figure 20.26. In the likely event that the data you exported to the SQL Server table is sorted in the order of the original Jet index you want to duplicate, you can mark the Sorted Data check box. Add a Fill Factor, if you want to reserve space in the data pages to add new records to a table with a clustered index—without needing to reorder the pages. In most cases, you need not specify Sorted Data or a Fill Factor.

    Figure 20.26. Confirming the addition of a new index to an SQL Server table.

  7. Click the Yes button to create the new index. If you receive a message that there is insufficient space to create the new index, use the SQL Administrator to expand the space within MASTER.DAT allocated to the northwind table.

  8. When indexing is complete, close the SQL Object Manager application.

You can verify that the index is present and is recognized by the SQL Server ODBC driver by reopening the dbo.Order_Details table in VisData and inspecting the last record to determine if a Recordset of the Dynaset type created over the table is updatable. Figure 20.27 demonstrates that Jet recognizes the newly-created PrimaryKey index. The PrimaryKey index and its properties appear at the bottom of the Table Structure dialog (see Figure 20.28.)

Figure 20.27. Verifying that the addition of a primary key index to a remote table results in an updatable Recordset object.

Figure 20.28. Displaying the properties of an index on a remote table.

Using SQL Passthrough to Improve Application Performance


Opening tables and manipulating client/server table data through the ODBC API is inherently faster than performing the same operations with the Jet database engine. This is because the Jet engine, the ODBC Driver Manager, and the ODBC driver constitute a series of separate layers, related to the layers of OSI network protocols described in the preceding chapter, through which each instruction must pass. In addition, Jet's query parser must process all queries written in Jet SQL. (Jet only parses the query once, however, if you use a persistent QueryDef object; therefore, using a parameterized QueryDef object is faster than executing a custom SQL statement each time you run a query.)

Most Visual Basic 4.0 and many Access production applications that connect to client/server databases with the ODBC API employ the SQL passthrough method to create Recordset objects of the Snapshot type based on SQL SELECT statements. SQL passthrough sends the SQL statement, verbatim, directly to the server. The server executes the query and returns only the specified rows to create the Recordset object in your Visual Basic 4.0 application. Thus, the SQL passthrough method improves performance for the following reasons:



The conditions under which the Jet database engine processes locally parts of SQL queries intended for client/server RDBMSs is one of the subjects of the "JET Database Engine ODBC Connectivity White Paper," described in the "Connections, Threads, and Symmetrical Multiprocessing" section earlier in this chapter.

To use SQL passthrough, you set bit 7 (decimal 64) of the masked intOptions argument of the OpenRecordset method with the dbSQLPassThrough constant, as in the following example:




Set rssQuery = dbNwind.OpenRecordset(strSQL, _



   dbOpenSnapshot, dbSQLPassThrough)

The value of strSQL is a string that contains the SQL SELECT statement you want the server to execute in the dialect of SQL supported by the server, not Jet SQL. To execute a SQL passthrough action query, such as an INSERT, UPDATE, or DELETE operation, invoke the Execute method, as in the following example:




dbNwind.Execute(strSQL, dbSQLPassThrough)

As noted in Chapter 5, "Learning Structured Query Language," each server back-end has its own flavor of ANSI or pseudo-ANSI SQL. Therefore, it is likely that you must rewrite any SQL statements that previously were sent to the Jet database engine in another dialect of SQL to make your SQL passthrough queries run without choking on special Jet SQL syntax. Chapter 22 provides examples of passthrough queries that use SQL Server's Transact-SQL dialect.

The SQL passthrough option of the OpenRecordset method also can be used with the appropriate SQL syntax to execute stored procedures contained in the server database. The syntax for executing stored procedures with SQL statements differs with each RDBMS that supports stored procedures. SQL Server stored procedures are one of the subjects of Chapter 22.

Summary


This chapter emphasized that creating Visual Basic 4.0 client/server, front-end applications does not differ substantially from the design of similar applications that connect to conventional desktop databases with the Jet database engine. The principal issues for the Visual Basic 4.0 database developer are setting up the server database and the ODBC data source(s) for the client/server back-end. Thus, much of this chapter was devoted primarily to a discussion of the characteristics of a powerful client-server RDBMS, Microsoft SQL Server versions 4.2 and higher, and the version 2.5 of the Microsoft 32-bit ODBC API. The chapter concluded with a brief description of how you use the OpenRecordset and Execute methods with the SQL passthrough option to improve the performance of client-server database front-ends that use multiple-tier ODBC drivers.

The next chapter describes how to create mail-enabled Visual Basic applications that use the MAPI OLE control. Applications that take advantage of use the Schedule+ Object Library also are discussed.

Previous Page Page Top TOC Next Page