This article may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. To maintain the flow of the article, we've left these URLs in the text, but disabled the links.


MIND


Beyond the Browser
beyond@microsoft.com        Download the code (3KB)
Ken Spencer

The Data Component DTC
T
he Data Component design-time control (DC DTC) makes it easier to solve many of the nagging problems you encounter when dealing with n-tier components. Available from MSDN Online at http://msdn.microsoft.com/vinterdev/downloads/samples.asp, the DC DTC works with Visual InterDev 6.0 and middle-tier COM objects. The DC DTC sits between your ASP code and the component and provides the interface between them. Your interface to the DC DTC works like the Recordset design-time control. In fact, the DC DTC supports most of the Recordset methods, properties, and events, as well as a few of its own.

      Since the DC DTC works like the Recordset DTC, it can serve as a data source in your ASP code. This lets you bind other design-time controls directly to a DC DTC. You can also implement the DC DTC in either ASP or DHTML. Whether you implement the DC DTC in ASP or as DHTML on the client, the data component object linked to the DC DTC runs on the server.

       So what is a data component that can be used with the DC design-time control? The data component is a standard COM component that includes methods returning an ADO recordset. You can build the component in any language that supports COM and allows you to return ADO recordsets, such as Visual Basic® or Visual C++®. You create the component so that certain methods return ADO recordsets as their return values. The recordsets are then passed to the DC DTC. More on this in a moment.

       To perform updates, additions, deletions, and other similar operations, the DC DTC merely serves as a middle layer to your object's methods. When you create ASP applications using the DC DTC, the DC DTC simply executes methods in the object assigned to it to perform actions such as an insert or update. This ability will enable you to use existing objects with just a bit of tweaking.
To take a look at this new design-time control, let's walk through its sample Sales demo files. This sample is interesting in that it implements the DC DTC in DHTML.

       Before you can use the DC DTC, you must install it onto your system. There are also several files that must be copied to the _ScriptLibrary directory in every project in which you will use the DC DTC. These files implement the runtime code. Note that all of my work with the DC DTC has been on beta versions, so there may be some differences in the release version you can now download. Check the readme files and documentation provided with the release software for additional information.

       After you have installed the DC DTC, you can use it in your applications by adding it to pages from the Toolbox. If the DC DTC does not show up in the Toolbox, add it by right-clicking the Toolbox and selecting Customize Toolbox. Next, select the checkbox to the left of the component in the Customize Toolbox dialog (see Figure 1). If the DC DTC does not show up in the Toolbox or the Customize Toolbox dialog, there is a problem with the installation and you should reinstall the DC DTC.
Figure 1: Adding the DC DTC to Your Apps
Figure 1: Adding the DC DTC to Your Apps

       To use the DC DTC with a new page, drag it from the Toolbox and drop it on a page just like you would a Recordset design-time control, then open the DC DTC properties. Figure 2 shows the properties for dcStores. First, change the name of the DC DTC. Next, specify the ProgID of the object the DC DTC links to by specifying the object's ProgID. The ProgID is created when you create the object in a language like Visual Basic. For a Visual Basic-based component, the first part of the ProgID is the project's name and the second part is the object (class) name. Finally, select the scripting model. The sample implements the DC DTCs on the client using DHTML.
Figure 2: dcStores Properties
Figure 2: dcStores Properties

Using the Data Component to Return Recordsets

       You should not use special characters such as !, @, #, $, %, ^, &, *, (, and ) in your field or database names. I learned long ago that it's best to stick with standard characters and naming conventions for database, table, and column names. Microsoft® Access may allow special characters in a name. You can use spaces in table and column names in Microsoft Access databases. However, these databases must be modified when moved to SQL Server™ because SQL Server does not allow spaces in names. The same thing applies for Windows NT® Server and user names—and almost any type of name for an application or a system. Some allow special characters in names, while others do not. Stick with standard alphanumeric characters and you are almost always ok.

       To use the DC DTC to retrieve data, your object must support a method that returns an ADO recordset. The Visual Basic code shown in Figure 3 has several methods in the Sales class that perform the functions used by the DC DTC in the Sales.asp code.
Let's look at one of the methods that returns a recordset. The topTitlesbyStore method retrieves titles by store (using store_id). This method calls the getRecordset function, which performs all the ADO work. The getRecordset function returns the resulting recordset to the topTitlesbyStore method, which stores it in the rsTable1 variable. The code then sets the return value of the topTitlesbyStore method to the recordset using this statement:



 Set topTitlesbyStore = rsTable1
       To retrieve the recordset using the DC DTC, you must create an event handler for the ongetrecordsource event in your ASP code. The entire script for Sales.asp is shown in Figure 4. This page contains two DC DTC controls, dcStores and dcSales. The event handler for the dcStores ongetrecordsource looks like this:


 Function dcStores_ongetrecordsource()
     if not IsEmpty(dcStores.getParameter(0)) then
         dcStores.source.StateFilter = dcStores.getParameter(0)
     end if
     set dcStores_ongetrecordsource = dcStores.source.getStores()
 End Function
       The code looks more complex than it is. This event handler sets the StateFilter property of the Sales object to the first parameter in the DC DTC if the parameter has been set. The parameter is set in the DC DTC on the client in DHTML, but the server ASP code can read the value from it in ASP using the DC DTC. The value is just passed in the DC DTC as part of its recordset. If the DC DTC is implemented in server-side code, it works the same way. This makes writing code easy.

       The Source child object of any DC DTC is a reference directly to the object that is used by the DC DTC. This lets you access the objects methods and properties directly.

       The last line (Set …) of the ongetrecordsource event handler executes the getStores method in the Sales object, then sets the return value of the event handler to the return value of the method. This is how the DC DTC gets the return recordset. You simply execute the method that returns the ADO recordset, then set the return value of the event to the return value of that method.
The dcStores parameter is set by the lbStates_onchange event. This event fires on the client when the user selects a state from the list to filter the selected stores:


 dcStores.setParameter(0,lbStates.getValue(lbStates.selectedIndex));
       After the parameter is set, the requery method of dcStores is executed:


 dcStores.requery();
       This causes dcStores to fire its ongetrecordsource event, which I discussed earlier. The ongetrecordsource event will fire any time the page is opened or when the requery method is executed.

       This sample demonstrated how the user interaction goes to and from dcStores, and how dcStores acts as a recordset. If I had used a server-side implementation of the DC DTC, the design-time control would fire the events in ASP code and the application would work the same way, except the events all happen on the server.

Performing Other Actions

       The DC DTC also allows you to perform actions such as updates and inserts in the recordset. This part of the code is quite simple; the object's methods can be standard methods that take parameters and perform actions using ADO or any other type of data access, even performing nontraditional actions such as sending email, using Microsoft Message Queuing, or writing to files.

       Take a look at the updStore method in Figure 3. This method takes a series of parameters, then constructs a recordset and finds the store to update in the recordset. This is no different than a method in any business object or even a two-tier application that updates data in a database. You can use stored procedures, SQL, or any other method to perform the update action—the DC DTC does not care or even know. This is one of the advantages of using the DC DTC to link with the middle-tier object; the object becomes a true black box and you do not need to understand how the object works, only that the object provides access to the data you need. The DC DTC and the object take care of the marshaling and implementation, in addition to data access.

       To perform update, insert, or delete actions in your ASP or DHTML code, you can use one of the following DC DTC events to execute the method in the object:
Action
DC DTC Event
Delete
ondelete
Insert
oninsert
Update
onupdate

       In Sales.asp, each event handler simply takes the values from the user input and feeds them to the corresponding method of the object as parameters. The following ASP code example implements the event handler for an insert action to the recordset:



 Function dcStores_oninsert() _
     dcStores.source.newStore dcStores.fields.getValue(0), _
     dcStores.fields.getValue(1), _
     dcStores.fields.getValue(2), _
     dcStores.fields.getValue(3), _
     dcStores.fields.getValue(4), _
     dcStores.fields.getValue(5)
 End Function
       You can see that this event simply executes the newStore method of dcStores and passes in the values of the dcStores current record.
To trigger the DC DTC event, you use the standard recordset methods. The following client event handler executes when the user clicks the button (btInsert) to add a new store:


 function btInsert_onclick() {
     dcStores.addRecord();
 }
       When addRecord executes on the client (remember, this code is JScript® running in the browser), dcStores causes the dcStores_oninsert event handler to execute on the server, which in turn executes the newStore method in the Sales object.

       The other events work in a similar manner. Your code interaction with the DC DTC causes the event to fire, then the event handler executes the object's method or other code to handle the event. When the user performs an action that results in an update action, the following client event handler executes:


 function btUpdate_onclick() {
     dcStores.updateRecord();
 }
       The updateRecord method causes dcStores_onupdate to fire:


 Function dcStores_onupdate()
     dcStores.source.updStore _
     dcStores.fields.getValue(0), _
     dcStores.fields.getValue(1), _
     dcStores.fields.getValue(2), _
     dcStores.fields.getValue(3), _
     dcStores.fields.getValue(4), _
     dcStores.fields.getValue(5)
 End Function
       This code takes the values from the DC DTC recordset and passes them to the updStore method in the Sales object.

       You can also use multiple DC DTCs on a single page. This lets you use different methods to create recordsets or perform other actions. For instance, the Sales.asp file contains two DC DTCs, one for Sales and the other for Stores. The methods in the object for both DC DTCs are based upon the same Sales object—the DC DTC events just execute different methods in the appropriate event handler for each DC DTC action.

Conclusion

       There are a number of other DC DTC methods you can use. As I mentioned earlier, the DC DTC implements most or all (I haven't counted them) of the Recordset DTC object's events, methods, and properties. The Source child object also gives you direct access to the methods and properties of the middle-tier object to which the DC DTC links.

       In a development environment where you are working on one workstation and the application is running on another workstation, you should install the middle-tier component on both the production server and the developer workstations. This will allow you to use and test the application locally on the workstation and run and test the application on the server. If the component is only registered on the server, then you can't test the application on the workstation unless you use DCOM to access the component.

       Also, by registering the component on the workstation, you can take advantage of IntelliSense® statement completion when you use the Source child object. To register the component locally, you don't need to copy the component to your workstation, you only need access to the component across your LAN. This lets you keep one copy of the component on the server and access it from both your workstation and the server as if it is a local component in both places.

From the April 1999 issue of Microsoft Internet Developer.