Teach Yourself Database Programming
with Visual C++ 6 in 21 days


Day 11
      Multitier Architectures



Multitier development is transcending traditional client/server programming. The reason for this transition is the fact that multitier applications promise to combine the verve and panache of client/server applications with the ruggedness and scalability of the big iron (mainframe systems).

The tools for multitier programming are relatively new, and developers who have knowledge of multitier development are at a premium. Today's material provides you with information about some of the tools for performing multitier development on the Windows platform.

Today's development work uses Microsoft Internet Information Server (IIS) with Internet Explorer version 4.0 (IE4). If you have use of IE4 and IIS (or Microsoft Personal Web Server, which is compatible with IIS), you will be able to perform all the programming tasks described today. If not, you will have to learn some of these techniques without being able to try them yourself.

Although this is a Visual C++ book, today's work does not involve writing any C++ code. Instead, you will examine some XML code and write a little HTML code. You will also write some Active Server Page code to learn how to use Remote Data Services (RDS). You will get back to writing C++ code tomorrow when you build COM server components that run under Microsoft Transaction Server and Internet Information Server.

Today you will

Layered Architecture

Creating database applications for systems where the software runs on multiple computers over a network has never been easy. The most difficult part of developing such a system is designing it. In fact, limitations in the design of typical client/server systems have hindered the growth of client/server computing.

One of the limitations in the design of typical client/server systems is that the software is generally not layered effectively. Client/server software is often monolithic.

In monolithic software, the code for the different types of operations is intermingled, and this code is all baked into traditional Windows EXEs and DLLs. Monolithic software has proven to be insufficiently flexible and scalable for many client/server applications to be successful.

Using a layered architecture is a proven alternative to monolithic software. The value of a layered architecture is best understood by examining a very successful layered architecture, the OSI model for network software.

The OSI Model

Not too many years ago, it was difficult to send data between different computer systems, because each computer manufacturer had its own standards for network communications. The computers from different manufacturers used different communications protocols, and the computers typically could not talk to each other.

In the late 1970s, the International Standards Organization (ISO) created a model to standardize the various protocols for network communications. This model is called Open Systems Interconnect, or the OSI model.

The OSI model enables network communications software to be written in layers, with well-defined interfaces between the layers. The abstractions provided by these layers now make it possible for disparate computer systems to communicate with each other over a network.

The OSI model consists of seven layers. In the OSI model, each layer was created to provide a different level of abstraction. Each layer in the model performs a well-defined type of operation and has a well-defined set of interfaces. The OSI layers are shown in Figure 11.1.

Figure 11.1 : Layers of the OSI model.

The layers of the OSI model shown in Figure 11.1 are

NOTE
The designers of the OSI model carefully crafted the interfaces between the OSI layers so that the layers would be independent. The interfaces were created in such a way as to enable the implementation of one layer to be changed without the need to change the implementation of its neighboring layers.

The OSI model has proven to be very successful. Disparate computer systems can now readily communicate with each other using this layered approach.

TCP/IP is a protocol that adheres to the OSI model. Figure 11.2 illustrates how the layers of TCP/IP map to the layers of the OSI model.

Figure 11.2 : How TCP/IP layers correspond to the OSI model.

TCP/IP is the protocol of the Internet. As you will see later, the nature of TCP/IP and the nature of the OSI model figure prominently in the way multitier applications are developed.

Layered Architecture for Multitier Applications

When you build multitier applications, you can apply important lessons from the OSI model to make your applications successful.

NOTE
When you build multitier applications, you must carefully craft the interfaces between the tiers so that the tiers are independent. You need to create the interfaces in such a way that the implementation of one tier can be changed without the need to change the implementation of its neighboring tiers.

Interfaces and abstractions are the two pillars on which multitier applications rest. Each tier that provides an effective level of abstraction has interfaces that are understandable and distinct. Distinct interfaces between the tiers enable the tiers to be updated independently of each other.

In traditional C++ development, programmers typically attempt to create layered architectures by using C++ classes. The classes provide the abstractions, and the public member functions provide the interfaces.

The C++ approach is good but is hampered by the fact that the C++ classes are usually compiled into Windows EXEs and DLLs, without using COM interfaces. As you discovered in Day 9, "Understanding COM," Windows EXEs and DLLs that don't support COM interfaces are invariably bound together by build-time dependencies. A non-COM Windows EXE file and the DLL files it uses must all come from the appropriate build of the software.

Any time you have build-time dependencies between binaries in an application, you have a monolithic application. In a multitier application, you might have client pieces running on hundreds of computers. You don't want to have to update all the software on every client machine every time you make some small alteration to the software.

NOTE
In multitier applications, you want to avoid build-time dependencies between the tiers. You want to be able to update the software on one tier without having to update the software on its neighboring tiers.

This issue of being required to update all the client machines is a frequent problem in traditional client/server applications. In many client/server systems, even a small change in the server software can necessitate a massive update of all the client software.

These massive client software updates are often caused by the build-time dependencies between EXEs and DLLs, which make it impossible to update one binary without updating them all.

Another feature in client/server applications that exacerbates the need to update all the client software every time is fat client software. Fat client software does not refer to software you write for fat clients. Rather, a fat client is a piece of software that runs on a client computer and contains both code to process data and code to present it to the user.

As you can see in Figure 11.3, fat clients contain business logic. This business logic may include code for formulas or rules to perform calculations on business data, or it may include code that accesses tables and fields directly in a business database.

Figure 11.3 : Client/server architecture with fat clients.

Note in Figure 11.3 that the UI portion of the client tier communicates directly with the database. This occurs in client applications that use direct SQL statements and/or databound controls, which tie fields and records in the database directly to elements of the user interface.

Thin is in

Thin client software is software that runs on client machines and contains only UI (or presentation) code. With thin clients, the need to update all the client computers every time the application is updated is greatly reduced. Thin clients enable you to change server software components without having to update all the client software every time. A simple multitier architecture is illustrated in Figure 11.4.

As you can see in Figure 11.4, multitier applications use thin clients that do not contain business logic. The business logic is typically moved to a middletier of some sort. In some multitier applications, the middletier software runs on its own machine. In other multitier applications, the middle-tier software runs on the same machine as the data-tier software.

Figure 11.4 : Multitier architecture.

A good example of a thin client is a Web browser. All that a Web browser typically does is presentation. Contrast a Web browser with ADOMFC1.EXE, the MFC application you have been working on in this book. As you know, ADOMFC1.EXE performs more than just presentation tasks.

ADOMFC1.EXE uses ADO to connect with the database and then issues SQL statements to SELECT, UPDATE, INSERT, and DELETE data from tables in the database. ADOMFC1.EXE has intimate knowledge of the database. The code in ADOMFC1.EXE knows the names of the tables and their fields, and the relationships between the tables. If the database schema were to change, ADOMFC1.EXE would very likely need to be changed as well.

ADOMFC1.EXE is a fat client. ADOMFC1.EXE illustrates the requirement for client software to be frequently updated in client/server systems. If ADOMFC1.EXE were installed as the client software for a client/server application, a small change in the database could necessitate an update of all the instances of ADOMFC1.EXE on the client machines.

The nature of the connection that ADOMFC1.EXE uses with the database also increases its interdependence with the data tier. When ADOMFC1.EXE uses the ADO Connection object to make a connection to a database such as SQL Server, it makes an interprocess communication (IPC) connection with the database. The interprocess communication mechanism is typically named pipes or TCP/IP sockets.

It was mentioned earlier that the nature of TCP/IP and the OSI model figures prominently in the way multitier applications are developed. Here's how.

Interprocess communication with named pipes and/or sockets is done at the OSI application layer. For security reasons, interprocess communication is typically not used over the Internet. Using interprocess communications between software tiers makes a wide-open connection and enables a broad interface between the software tiers.

An IPC connection can be thought of as a hard-wired connection to the database that enables ADOMFC1.EXE and the database to have a high level of interaction. ADOMFC1.EXE can modify data in the database almost instantaneously. Round trips between ADOMFC1.EXE and the database happen relatively fast. ADOMFC1.EXE can scroll through large sets of records very quickly. ADOMFC1.EXE can also lock records and open transactions in the database and keep them as long as it likes.

Interprocess communication between software tiers enables a broad interface between the tiers. However, a broad interface between tiers is not always desirable if you want the tiers to be somewhat independent of each other.

Web browsers and Web servers use the HTTP protocol, which is a connectionless protocol built on TCP/IP. HTTP also operates at the application layer of the OSI model. However, using HTTP for communications between software tiers provides a much narrower interface between the tiers than named pipes or TCP/IP sockets do. A client application can't make an IPC connection to a database with HTTP. This means an application that uses HTTP can't enjoy the high level of interactivity with the database that an IPC connection would provide. HTTP's narrower interface, in effect, forces the software tiers to be more independent of each other.

Web Browsers as Thin Clients

Web browsers can make a good client tier. Because Web browsers perform only UI tasks and the interface between the Web browser and the Web server (HTTP) is so distinct, the Web browser and the Web server can be quite independent of each other in terms of software update requirements.

Web browsers can be used for applications that run on the Internet (more specifically, the World Wide Web) and also can be used in applications that run over a LAN in an intranet. The term intranet is used to describe the application of Internet technologies on internal corporate networks. With an intranet, you can have a Web server that is internal to your corporate LAN, and information from that Web server can be accessed by machines on the LAN that runs Web browsers.

Multitier applications that use Web browsers as clients use a Web server such as Microsoft (IIS) in their middle tier. In such applications, Microsoft Transaction Server (MTS) is sometimes used in conjunction with IIS on the middle tier. You will explore MTS tomorrow.

Multitier applications that use Web browsers and IIS typically use an RDBMS, such as SQL Server or Oracle, as the data tier. Later today, you will use a middle-tier software component that retrieves data from the database and sends it through IIS to software on the client tier.

Tomorrow you will write your own component that runs under MTS and IIS. You will be able to use this component on the middle tier to send data from a database to browsers over HTTP, as well as to fat DCOM clients such as ADOMFC1.EXE.

Database Data and the Internet

If you do use a Web browser for the client piece of your multitier application, how do you get the data from the database to the Web browser?

CGI-The Original Technique for Interfacing Databases with Web Servers

The tools for using a Web browser as the UI to a database application have been evolving rapidly. Figure 11.5 shows how it was done in the early days of the Web.

Figure 11.5 : Interfacing a Web browser to a database by using CGI.

As you can see from Figure 11.5, you could write a CGI application, which is an EXE that accepts and fulfills requests from the Web server for data from the database. One drawback of CGI is the fact that for every concurrent user that is hitting your Web server, the Web server has to launch another instance of the CGI EXE. Launching an EXE for each concurrent user can put a strain on the Web server machine.

DLLs and Server Scripts-An Improved Technique for Interfacing Databases with Web Servers

Microsoft and Netscape each developed their own improvements to the CGI model. In the improved models, a DLL that runs in the Web server's process space is used instead of a CGI EXE. This is illustrated in Figure 11.6.

Figure 11.6 : Interfacing a Web browser to a database by using DLLs.

In the case of Microsoft IIS, the DLLs that provide an interface between IIS and a database are called ISAPI DLLs. Because DLLs run in the Web server's process, they place a lighter load on the Web server machine than CGI EXEs.

Microsoft has developed a technology called Active Server Pages (ASP), which is built on its ISAPI DLL technology. ASP has a server-side script interpreter that enables you to run JScript and VBScript scripts on the Web server. These scripts can make calls to COM servers and send the results out through the Web server to Web browsers. The ASP technology is illustrated in Figure 11.7.

Figure 11.7 : Interfacing a Web browser to a database by using ASP.

As you can see in Figure 11.7, an ASP script can call a COM server that can communicate with a database. The ASP script can then send the data from the database out through the Web server to Web browsers. Later today, you will use ASP to communicate database data to Web browsers.

The XML Files

Extensible Markup Language (XML) provides a way to describe and exchange data in Web-based applications. XML complements Hypertext Markup Language (HTML). HTML enables the displaying of data, whereas XML provides ways to describe and transmit data.

XML enables metadata, or data about data, to be imbedded with data and sent over the Web. You could think of XML as a way to describe and transmit data in an HTML-like format.

As of this writing, XML is still making its way through the standards process. XML is in its infancy now, but it will become a vital technology in multitier applications in the future.

Listing 11.1 shows some XML code. The intent here is to give you a feel for what XML looks like.


Listing 11.1  A High-level Wrapper Function in MSADO15.TLI

 1:  <?XML version="1.0" encoding="UTF-8" ?>
 2:  <Sales>
 3:  <s:schema id='SalesSchema'>
 4:
 5:    <elementType id="custnumber">
 6:      <string/>
 7:    </elementType>
 8:
 9:    <elementType id="Customer">
10:      <element id="c1" type="#custnumber"/>
11:      <key id="k1"><keyPart href="#c1"/></key>
12:    </elementType>
13:
14:    <elementType id="buyer">
15:      <string/>
16:      <foreignKey range="#Customer" key="#k1"/>
17:    </elementType>
18:
19:    <elementType id="partnumber">
20:      <string/>
21:    </elementType>
22:
23:    <elementType id="Purchase">
24:      <element type="#partnumber"/>
25:      <element type="#buyer" occurs="ONEORMORE"/>
26:    </elementType>
27:
28:  </s:schema>
29:
30:  <Customer><custnumber>Cust003</custnumber></Customer>
31:
32:  <Customer><custnumber>Cust938</custnumber></Customer>
33:
34:  <Customer><custnumber>Cust501</custnumber></Customer>
35:
36:  <Purchase>
37:    <buyer>Cust003</buyer>
38:    <buyer>Cust938</buyer>
39:    <partnumber>CLAP-003</partnumber>
40:  </Purchase>
41:
42:  <Purchase>
43:    <buyer>Cust501</buyer>
44:    <buyer>Cust938</buyer>
45:    <partnumber>MIC-92823</partnumber>
46:  </Purchase>
47:
48:  </Sales>

Listing 11.1 illustrates how data from a relational database could be represented in XML. XML is text-based, and as you can see, is similar to HTML.

Line 1 indicates the version of XML. XML code is rigidly nested. An XML document is made up of XML elements, each of which consists of a start tag, such as <Sales> in line 2, and an end tag, such as </Sales> in line 48. The information between the two tags is referred to as the contents.

Tags annotate XML code as they do HTML code. In HTML, each tag indicates how something should look. However, in XML each tag indicates what something means.

Line 3 is the start tag for the schema called "SalesSchema". Line 28 is the end tag for the schema. A schema in XML is similar to a schema in a relational database. Lines 3-28 declare a schema that relates buyers and partnumbers in a one-to-many relationship called Purchases. You will recall that you explored database design and data relationships in Day 7. (In a relational database that corresponds to the XML schema in Listing 11.1, Purchases would be a table that contains two fields: partnumber and buyer.)

To declare the one-to-many relationship, lines 5-26 contain a series of elementType declarations. Lines 5-7 declare a class (or element type) with an id of "custnumber" that has a data type of string. Lines 9-12 declare an element type of "Customer" that has custnumber as an element (or field). Note that custnumber is the key field. (In real life, the Customer element type would have additional fields, but they are not shown here for simplicity.)

Lines 14-17 declare an element type of "buyer", which has a Customer as a foreign key field. Lines 19-21 declare a partnumber element type that is string data. Lines 23-26 declare an element type of "Purchase", which contains a partnumber and a buyer. You will notice that in line 25, buyer is indicated as ONEORMORE, meaning there can be multiple buyers per partnumber.

Line 28 marks the end of the schema. The information that comes after line 28 is the actual data. This XML data conforms to the XML schema, like records in a database.

Lines 30-34 are three instances (or records) of customers. Lines 36-46 are two instances of Purchases. Each purchase lists the partnumber and the customers who bought it. If you were to place the Purchases information in a table in a relational database, the table would consist of two fields (partnumber and buyer) and would contain four records.

A full explanation of how to parse and process XML code is beyond the scope of this book. However, you could begin to get your feet wet with XML by entering the code in Listing 11.1 into an XML file. You could then use the XML parsing sample(s) from Microsoft's Web site to process it.

To enter Listing 11.1 into an XML file, run Visual Studio, select the File, New menu, and tell it to create a new HTML page. (The HTML page needn't be part of any of your projects in Visual Studio.) Then type in the code in Listing 11.1 and save it as an XML file.

Currently, IE4 is the only XML-aware browser. Other Web browsers currently cannot read XML files.

A potentially useful tool for XML is the Microsoft XSL Processor. The XSL Processor takes XML code and converts it to HTML that can be displayed in almost any browser. This is illustrated in Figure 11.8.

Figure 11.8 : Using XLS with XML to get HTML.

Microsoft offers an XSL command-line utility and an XSL ActiveX control to make it easy and productive to get HTML from XML.

You can find more information on XML and XSL by pointing your Web browser to http://www.microsoft.com/XML. You will find information and documentation on XML, as well as sample programs for parsing and processing XML code. You can obtain further XML development information as part of the Microsoft Internet Client SDK at http://msdn.microsoft.com/developer/sdk/inetsdk.

What Color of Edsel Would You Like?

So far today, you've read about using Web browsers as the client piece of multitier database applications. This, of course, means putting database data into HTML and sending it to Web browsers. In actual practice, using HTML to display data from a database can make a pretty lame user interface. Listing 11.2 shows a typical model for displaying and processing database data in HTML.

NOTE
A full explanation of HTML is beyond the scope of this work. Listing 11.2 is intended merely to familiarize you with some of the limitations of using HTML-based Web pages as the UI for a database application.

To enter Listing 11.2 into an HTML file, run Visual Studio, select the File, New menu, and tell it to create a new HTML page. (The HTML page needn't be part of any of your projects in Visual Studio.) Then type in the code in Listing 11.2 and save it as an HTM file. You can view the page in IE4 by entering the full path and filename of the HTM file in the IE4 Address text box.


Listing 11.2  Database Data in HTML

 1:  <HTML>
 2:  <HEAD>
 3:  <TITLE>Database Data in HTML</TITLE>
 4:  </HEAD>
 5:  <BODY>
 6:  <CENTER>
 7:  <H1>Database Data</H1>
 8:  <BR>
 9:  <TABLE BORDER=1 WIDTH=80%>
10:  <THEAD>
11:  <TR>
12:  <TH>Field 1</TH>
13:  <TH>Field 2</TH>
14:  </TR>
15:  <TBODY>
16:  <TR>
17:  <TD>Record 1, Field 1 contents.</TD>
18:  <TD>Record 1, Field 2 contents.</TD>
19:  </TR>
20:  <TR>
21:  <TD>Record 2, Field 1 contents.</TD>
22:  <TD>Record 2, Field 2 contents.</TD>
23:  </TR>
24:  <TR>
25:  <TD>Record 3, Field 1 contents.</TD>
26:  <TD>Record 3, Field 2 contents.</TD>
27:  </TR>
28:  </TABLE>
29:  <BR>
30:  <TABLE>
31:  <TR>
32:  <TD>Field 1:<TD><INPUT NAME=Field1 SIZE=30>
33:  <TD>Field 2:<TD><INPUT NAME=Field2 SIZE=30>
34:  </TR>
35:  </TABLE>
36:
37:  <BR>
38:  <INPUT TYPE=BUTTON NAME="Update" VALUE="Save Changes">
39:  </CENTER>
40:
41:  <SCRIPT LANGUAGE="VBScript">
42:  SUB Update_OnClick
43:    MsgBox "Do some processing to update: " + Field1.Value + 
                " and " + Field2.Value
44:  END SUB
45:  </SCRIPT>
46:  </BODY>
47:  </HTML>

In browser/database applications, data from a database is typically placed in static HTML tables for the browser to display to the user. Lines 1-28 in Listing 11.2 are standard HTML for displaying a table of data.

Lines 30-35 place two text boxes on the page. Line 38 puts a button on the page. Lines 41-45 contain VBScript code with an Update_OnClick function that executes when the button is clicked.

The user-interface tools in HTML for enabling the user to edit, add, and delete database data are somewhat primitive. The idea with the page in Listing 11.2 is to display the data from the database in the HTML table and accept user input for changes to the data by using the two text boxes. When the user clicks the button, the Update_OnClick function would display the user's input in the HTML table or send the data to the server, or both. Unfortunately, there is no easy way in HTML to enable the user to navigate to a particular record and edit it. As you can see, HTML makes for a somewhat primitive data-base UI.

Any changes that the user does make have to be sent to the server singly as they are made or cached in variables in the HTML page and sent as a batch. Sending the changes singly as they are made might result in lots of time-consuming round trips between the browser and the server. Caching the variables in the HTML page and sending them as a batch requires you to write lots of code.

With the lag time of the data's round trips to the Web server, and with browsers' primitive UI tools, your spiffy new multitier application could end up looking like an Edsel. For all the weaknesses of fat client software, a fat client does give you database connections that are responsive and quick and state of the art UI programming tools for building an elegant user interface.

Wouldn't it be nice if there were some way to build a client tier by using Web browsers that have the UI and the data handling capabilities of fat clients?

Fortunately, there is a way you can get these fat client capabilities in a browser. You can use the IE4 browser, with ActiveX controls for the UI and with ADO Remote Data Service (RDS) to handle the data on the client and middle tiers.

Using ActiveX Controls and RDS to Build Elegant Thin Clients

You can use a variety of ActiveX controls to provide an elegant UI in IE4. These ActiveX controls are available from Microsoft and from a number of independent software vendors (ISVs). Evaluation versions of many of the controls can be downloaded for free from the vendor's Web sites. These ActiveX controls enable you to create a modern and complete UI in the IE4 browser. You will use one such ActiveX control today.

To enable robust data handling in a browser, Microsoft offers Remote Data Service. RDS is included in Microsoft's Data Access Components (MDAC). When you install MDAC, RDS is installed automatically. You will find instructions for setting up RDS by searching the Platform SDK documentation (in MSDN) for a document titled "Setting Up Remote Data Service."

NOTE
You need to install the RDS Address Book sample to get a particular ActiveX control required for your work today. The Sheridan grid control is an ActiveX control that (as of this writing) is included in the RDS Address Book sample.

The code that you will write today uses the Sheridan grid control. If you are unable to obtain the Sheridan grid control in the RDS samples, you can download a trial version of the Sheridan Data Widgets at http://www.shersoft.com/.

To test your installation of RDS, type in the code shown in Listing 11.3 and save it as an ASP file. To enter Listing 11.3 into an ASP file, run Visual Studio, select the File, New menu, and tell it to create a new Active Server Page. (The ASP page needn't be part of any of your projects in Visual Studio.) Then type in the code in Listing 11.3 and save it as an ASP file. Call it something like ClientTier.ASP. You can view the page in IE4 by entering the Web address of the ASP file in the IE4 Address text box.

To run the code in Listing 11.3, you must have IIS or Personal Web Server running on your machine. See the "Setting Up Remote Data Service" document in the Platform SDK documentation for more information.

Listing 11.3  A Database Client UI with the ActiveX Grid Control and RDS

 1:  <HTML>
 2:  <HEAD>
 3:  <TITLE>Client Tier</TITLE>
 4:  </HEAD>
 5:  <CENTER>
 6:  <H1>Remote Data Service and Sheridan Grid Control</H1>
 7:  <BR>
 8:
 9:  <OBJECT ID="GRID" WIDTH=600 HEIGHT=200 Datasrc="#ADC"
10:    CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>
11:    /MSADC/Samples/ssdatb32.cab"
12:    CLASSID="CLSID:AC05DC80-7DF1-11d0-839E-00A024A94B3A">
13:    <PARAM NAME="_Version"      VALUE="131072">
14:    <PARAM NAME="BackColor"     VALUE="-2147483643">
15:    <PARAM NAME="BackColorOdd"  VALUE="-2147483643">
16:    <PARAM NAME="ForeColorEven" VALUE="0">
17:  </OBJECT>
18:
19:  <OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
20:    ID=ADC HEIGHT=1 WIDTH = 1>
21:  </OBJECT>
22:
23:  <BR>
24:  <BR>
25:  <BR>
26:  <INPUT TYPE=BUTTON NAME="Execute" VALUE="Execute">
27:  <INPUT TYPE=BUTTON NAME="MoveFirst" VALUE="MoveFirst">
28:  <INPUT TYPE=BUTTON NAME="MovePrevious" VALUE="MovePrevious">
29:  <INPUT TYPE=BUTTON NAME="MoveNext" VALUE="MoveNext">
30:  <INPUT TYPE=BUTTON NAME="MoveLast" VALUE="MoveLast"> <BR><BR>
31:  <INPUT TYPE=BUTTON NAME="Update" VALUE="Update">
32:  <INPUT TYPE=BUTTON NAME="Cancel" VALUE="Cancel">
33:  </CENTER>
34:
35:  <SCRIPT LANGUAGE= "VBScript">
36:
37:  SUB MoveFirst_onClick
38:    ADC.Recordset.MoveFirst
39:  END SUB
40:
41:  SUB MovePrevious_onClick
42:    On Error Resume Next
43:    ADC.Recordset.MovePrevious
44:    IF ERR.Number <> 0 THEN
45:      ERR.Clear
46:    END IF
47:  END SUB
48:
49:  SUB MoveNext_onClick
50:    On Error Resume Next
51:    ADC.Recordset.MoveNext
52:    IF ERR.Number <> 0 THEN
52:      ERR.Clear
53:    END IF
54:  END SUB
55:
56:  SUB MoveLast_onClick
57:    ADC.Recordset.MoveLast
58:  END SUB
59:
60:  SUB Update_onClick
61:    ADC.SubmitChanges
62:    ADC.Refresh
63:    Grid.Rebind
64:  END SUB
65:
66:  SUB Cancel_onClick
67:    ADC.CancelUpdate
68:    ADC.Refresh
69:    Grid.Rebind
70:  END SUB
71:
72:  SUB Execute_onClick
73:    ADC.Server = "http://<%=Request.ServerVariables("SERVER_NAME")%>"
74:    ADC.Connect = "DSN=OrdersDb"
75:    ADC.SQL = "Select * from Products"
76:    ADC.Refresh
77:    Grid.Rebind
78:  END SUB
79:
80:  </SCRIPT>
81:  </BODY>
82:  </HTML>

Lines 1-7 in Listing 11.3 put up the title for the window and a heading. Lines 9-17 place the Sheridan ActiveX grid control in the page. Lines 19-21 place the Microsoft RDS DataControl (also called the Advanced Data Control or ADC) into the page. Lines 26-32 place several buttons on the page to enable the user to interact with the UI. Lines 35-80 contain VBScript code for handling button presses by the user. Lines 80-82 end the tags to indicate the end of the page.

The Microsoft RDS DataControl (ADC) is an ActiveX control that is instantiated on the client machine in the browser's process. When the user presses the execute button, lines 73-75 set the Server, Connect, and SQL properties in the ADC. Line 76 calls the ADC Refresh method. This method uses the Server, Connect, and SQL properties to tell the middle tier to connect to the database and issue the SQL query. The ADC then retrieves the records and caches them on the client machine.

Line 77 tells the grid control to rebind to the records. The grid actually does more than just display them. The grid enables the user to navigate through the records, using the code in lines 37 through 58. The user can edit the records' contents in the grid. The user can cancel those changes by clicking the Cancel button, which executes the code in lines 66-70. The user can commit the changes by clicking the Update button, which executes the code in lines 60-64. The output of Listing 11.3 is shown in Figure 11.9.

Figure 11.9 : The client tier page in IE4.

What happens behind the scenes with Remote Data Services is quite amazing. Figure 11.10 shows the architecture of RDS.

Figure 11.10: The RDS architecture.

Following is an explanation of the sequence in a typical RDS operation:

  1. A thin client, such as a browser, running on a client tier machine creates a local instance of the RDS.DataControl (perhaps it is bound to a grid control running in the browser).
  2. When the user makes a request for the data, RDS.DataControl creates a remote instance of RDSServer.DataFactory on the middle-tier machine and issues a query to the DataFactory object.
  3. The DataFactory object on the middle-tier machine uses OLE DB or ODBC to query the database on the data-tier machine.
  4. The database processes the query and sends all the records to the DataFactory object on the middle-tier machine.
  5. The DataFactory object stores all the records from the query in an OLE DB row set, called the server-side cache, which resides on the middle-tier machine.
  6. The DataFactory places an ADO Recordset interface on the row set and sends it to the client machine as the RDS.DataControl requests it.
  7. If configured to do so, with large amounts of data the RDS.DataControl can cause the grid control to become interactive very soon after the DataFactory begins sending data to the client machine.

Step 7 mentions a capability that RDS provides that could be crucial for applications that process large amounts of data. RDS enables the results of queries to be sent asynchronously.

The RDS.DataControl can be configured to retrieve data in the background or asynchronously. If the RDS.DataControl is retrieving the data in the background and the user tells it to MoveLast (move to the last record), user interactivity will cease until all the data is retrieved. If the RDS.DataControl is retrieving the data asynchronously and the user tells it to MoveLast, user interactivity will continue. The RDS.DataControl will move to the most recent record received and will continue to retrieve data asynchronously.

You can enable the asynchronous capabilities of RDS by using the code shown in Listing 11.4. Create a new ASP page for this code. Call it something like ClientTierAsync.ASP.


Listing 11.4  RDS Asynchronous Operations

  1:  <HTML>
  2:  <HEAD>
  3:  <TITLE>Client Tier</TITLE>
  4:  </HEAD>
  5:  <CENTER>
  6:  <H1>Remote Data Service and Sheridan Grid Control</H1>
  7:  <BR>
  8:
  9:  <OBJECT ID="GRID" WIDTH=600 HEIGHT=200 Datasrc="#ADC"
 10:    CODEBASE="http://<%=Request.ServerVariables("SERVER_NAME")%>
 11:    /MSADC/Samples/ssdatb32.cab"
 12:    CLASSID="CLSID:AC05DC80-7DF1-11d0-839E-00A024A94B3A">
 13:    <PARAM NAME="_Version"      VALUE="131072">
 14:    <PARAM NAME="BackColor"     VALUE="-2147483643">
 15:    <PARAM NAME="BackColorOdd"  VALUE="-2147483643">
 16:    <PARAM NAME="ForeColorEven" VALUE="0">
 17:  </OBJECT>
 18:
 19:  <OBJECT classid="clsid:BD96C556-65A3-11D0-983A-00C04FC29E33"
 20:    ID=ADC HEIGHT=1 WIDTH = 1>
 21:  </OBJECT>
 22:
 23:  <BR>
 24:  <BR>
 25:  <BR>
 26:  <INPUT TYPE=BUTTON NAME="Execute" VALUE="Execute">
 27:  <INPUT TYPE=BUTTON NAME="MoveFirst" VALUE="MoveFirst">
 28:  <INPUT TYPE=BUTTON NAME="MovePrevious" VALUE="MovePrevious">
 29:  <INPUT TYPE=BUTTON NAME="MoveNext" VALUE="MoveNext">
 30:  <INPUT TYPE=BUTTON NAME="MoveLast" VALUE="MoveLast"> <BR><BR>
 31:  <INPUT TYPE=BUTTON NAME="Update" VALUE="Update">
 32:  <INPUT TYPE=BUTTON NAME="Cancel" VALUE="Cancel">
 33:  <BR>
 34:  <INPUT TYPE=TEXT NAME=RsState SIZE =25>
 35:  </CENTER>
 36:
 37:  <SCRIPT LANGUAGE= "VBScript">
 38:
 39:  Const adcExecSync = 1
 40:  Const adcExecAsync = 2
 41:
 42:  Const adcFetchUpFront = 1
 43:  Const adcFetchBackground = 2
 44:  Const adcFetchAsync = 3
 45:
 46:  Const adcReadyStateLoaded = 2
 47:  Const adcReadyStateInteractive = 3
 48:  Const adcReadyStateComplete = 4
 49:
 50:  SUB ADC_OnReadyStateChange
 51:    Select case ADC.ReadyState
 52:      case adcReadyStateLoaded: RsState.Value = "Loaded"
 53:      case adcReadyStateInteractive: RsState.Value = "Interactive"
 54:      case adcReadyStateComplete: RsState.Value = "Complete"
 55:    END Select
 56:  END SUB
 57:
 58:  SUB MoveFirst_onClick
 59:    ADC.Recordset.MoveFirst
 60:  END SUB
 61:
 62:  SUB MovePrevious_onClick
 63:    On Error Resume Next
 64:    ADC.Recordset.MovePrevious
 65:    IF ERR.Number <> 0 THEN
 66:      ERR.Clear
 67:    END IF
 68:  END SUB
 69:
 70:  SUB MoveNext_onClick
 71:    On Error Resume Next
 72:    ADC.Recordset.MoveNext
 73:    IF ERR.Number <> 0 THEN
 74:      ERR.Clear
 75:    END IF
 76:  END SUB
 77:
 78:  SUB MoveLast_onClick
 79:    ADC.Recordset.MoveLast
 80:  END SUB
 81:
 82:  SUB Update_onClick
 83:    ADC.SubmitChanges
 84:    ADC.Refresh
 85:    Grid.Rebind
 86:  END SUB
 87:
 88:  SUB Cancel_onClick
 89:    ADC.CancelUpdate
 90:    ADC.Refresh
 91:    Grid.Rebind
 92:  END SUB
 93:
 94:  SUB Execute_onClick
 95:    ADC.ExecuteOptions = adcExecAsync
 96:    ADC.FetchOptions = adcFetchAsync
 97:    ADC.Server = "http://<%=Request.ServerVariables("SERVER_NAME")%>"
 98:    ADC.Connect = "DSN=OrdersDb"
 99:    ADC.SQL = "Select * from Products"
100:   ADC.Refresh
101:   Grid.Rebind
102:  END SUB
103:
104:  </SCRIPT>
105:  </BODY>
106:  </HTML>

The code in Listing 11.4 enables you to experiment with the asynchronous capabilities of RDS. To help understand what is happening with the asynchronous data transfer, refer again to Figure 11.10.

The code in Listing 11.4 is identical to the code in Listing 11.3, with a few additions. Line 34 adds a text box that will report on the status of the Recordset in the ADC. Lines 39-48 are constants that were copied from the RDS type library (in MSADCO.DLL). Lines 50-56 define a function that is executed automatically whenever the status of the ADC Recordset changes. Lines 95 and 96 set the ADC to asynchronous operation before the query is issued.

One apparent problem with the RDS DataControl is the fact that the client program will issue queries directly to the database. It would appear that the client application has direct knowledge of the database. However, it is important to remember that the code for the client tier actually exists on the middle tier in ASP files. Changing the database might necessitate changing the ASP files, but not the software on the client machines.

A level of abstraction could be created using stored procedures and views in the database. These database stored procedures and views could provide an interface layer to the RDS clients, underneath which the implementation of the database structure could change.

A potential problem with RDS is in the area of security. The DataFactory object on the middle tier enables anyone who can obtain a DSN, username, and password to issue SQL statements to the database. Those SQL statements could include DELETE statements to erase data in the database. For this reason, RDS is typically not used on the Internet. It could enable anyone with a browser to delete your data. Rather, RDS finds its greatest application in corporate intranets where the users are more trusted and security can be controlled more easily.

You can also use the RDS DataControl in your C++ programs. The ADC code and the type library reside in MSADCO.DLL. You can use the #import directive with MSADCO.DLL just as you do with MSADO15.DLL. The RDS DataControl interface is listed as IBindMgr in the type library.

Summary

Multitier applications promise easier updates and maintenance than traditional client/server applications. The tools for building multitier applications have evolved rapidly over the past few years. XML is a technology that will be widely used in the future to transmit data in multitier applications. Some of the more recent developments, such as ActiveX controls and RDS, promise to enable client/server-type development in an intranet environment.

Q&A

Q
Can I use XML in C++ programs?
A
Yes. You can use the XML parser from Microsoft to parse XML documents in C++ programs and retrieve their contents. In other words, you can use the XML parser to read the schema of XML documents and then read the data that the XML documents contain. There is at least one sample C++ program for XML parsing on the Microsoft Web site.
Q
Why is it so difficult to use HTML to build a UI for a database application?
A
The UI for a database application typically requires that the data be displayed in a table and that the user be able to navigate through the table and edit the content of rows in the table as needed. HTML does not provide these capabilities. This is why it is necessary to use an ActiveX control, such as a grid control, to build a good database UI.
Q
Do I have to use an ODBC DSN with the RDS DataControl, or can I specify an OLE DB provider?
A
You can use OLE DB providers as well as ODBC data sources with the RDS DataControl. To use an OLE DB provider, you would use "Provider=" and specify the name of the provider and the particular OLE DB data source.

Workshop

The Workshop quiz questions test your understanding of today's material. (The answers appear in Appendix F, "Answers.") The exercises encourage you to apply the information you learned today to real-life situations.

Quiz

  1. What are the two pillars on which multitier architectures rest?
  2. Why are thin client programs often more desirable than fat client programs?
  3. How does the purpose of XML differ from the purpose of HTML?
  4. What COM objects are instantiated, and where are they instantiated, in a typical RDS application?
  5. What is the security risk posed by the RDS COM servers?

Exercises

  1. Create a table in your database that contains 10,000 records and query it with RDS to become familiar with the asynchronous operation of RDS.
  2. Create a new MFC application that uses #import with MSADCO.DLL. Make this C++ application use the ADO DataControl to perform a function that is similar to the ASP code in Listing 11.4.

© Copyright, Sams Publishing. All rights reserved.