Although ADO Recordsets offer access to only one row of data at a time, this does not mean that a Recordset must access the underlying data store every time the cursor moves. Internally, a Recordset can cache multiple rows of data. This caching capability is an important part of building scalable distributed applications.
Consider a scenario in which thousands of users are accessing an online store over the Internet. The catalog of items for sale is probably maintained in a database. If each user maintains a unique connection to the database itself for the entire time he or she browses the store, there is a strict limit on the number of simultaneous shoppers: the number of database connections available on the database server. If, on the other hand, database connections are used only while blocks of data are being read from the database, a single connection can support many users. In addition, if a large block of data can be sent back to the user's machine, the user can browse the catalog with fewer database server accesses. This not only can reduce network traffic, it can also make the online store seem more responsive to the user.
The MDAC technologies that help make this scenario a reality are ADO disconnected Recordset and Remote Data Service (RDS). These features were originally introduced under the name Advanced Data Connector (ADC), but they are built into ADO versions 1.5 and later. The RDS architecture is shown in Figure 3-5.
Figure 3-5. The RDS architecture.
A disconnected Recordset object is simply a Recordset object that has been dissociated from its Connection object. Disconnected recordsets do not retain locks on the underlying data store. Instead, all the data for all the rows is cached with the Recordset. If a Recordset is modified and the changes are saved back to the data store, OLE DB checks each modified row for conflicting updates in the data store—in other words, it checks whether someone else has modified the row since the Recordset was cached. If so, a conflict is reported to the application so that it can decide what to do.
RDS provides a client-side cursor engine for disconnected recordsets. It also provides a very efficient service for marshaling recordsets between machines, over either the Internet or an intranet. This means that a server application can generate a set of data and copy it to a client application, and the client application can browse the data as if it were connected to the actual data store. RDS also provides a way to bind Recordsets to data-bound controls, which can greatly simplify writing this type of client application.
RDS provides three components to help developers write applications: RDS.DataControl, RDSServer.DataFactory, and RDS.DataSpace. An RDS.DataControl object is used to bind data-bound ActiveX controls to Recordset objects. Client applications use RDS.DataControl to browse or modify a Recordset. RDSServer.DataFactory is essentially a generic business object for communicating with data sources. It contains no business rules or other application-specific logic.
The Recordset object itself is obtained in one of two ways. First, the Recordset can be created implicitly by RDS.DataControl. Properties of RDS.DataControl are set that identify the data server and query to be used. When the Refresh method is called, an RDSServer.DataFactory object is used behind the scenes to create the Recordset. Second, custom business objects can be defined that return disconnected recordsets. RDS.DataSpace objects are used to create client-side proxies to these business objects. The client-side proxy does whatever is necessary to communicate with the business object. Once the proxy has been created, the application can call whatever method returns a Recordset; it then sets the Recordset property of RDS.DataControl.
In this book, we use the second method exclusively. Middle-tier business objects will use data objects to create ADO disconnected recordsets. These Recordset objects will be passed back to the presentation layer using RDS. Presentation-layer client applications will use RDS to bind the Recordsets to data-bound controls.
In intranet scenarios, DCOM can be used to transfer the Recordsets between the client and server machines. In Internet scenarios, however, HTTP will normally be used. In this case, RDS provides services to manage the HTTP communication. An Internet Server API (ISAPI) extension, Advanced Data ISAPI (ADISAPI), is installed on the Web server. ADISAPI does the work required to handle requests for Recordsets from client-side business object proxies. It creates server-side objects, calls the methods required to generate the Recordset, and converts the data to an efficient form for transmission back to the client. ADISAPI and the business object proxies handle all the details of actually transmitting the data via HTTP.