12
Building an ADO Data Layer Under MTS
This may be the most important chapter you read in this book. In fact, it may change the way you think about web development. In this chapter we're going to discuss how to create an ActiveX server that wrappers query execution while running under MTS. Why is this so important? Well, you're about to find out.
Building scalable web applications is becoming more and more important in today's development arena. The need for web developers is growing rapidly as more and more businesses seek to establish powerful corporate Intranets, e-Commerce shopping sites, business-to-business Internet applications and so on. Not only are the numbers of web solutions growing, so is the number of simultaneous users that these solutions must be capable of handling. When you consider all of these factors together, it should be clear that the need for scalable and maintainable solutions is inescapable.
Hopefully this chapter will give you a feel for how the ADO data layer fit into this picture and how this can improve your enterprise applications. We will cover the following:
q Why use an ADO data services layer? We'll cover many of the benefits, including:
a. encapsulation of code
b. increased scalability
c. support for XML as well as arrays and the standard ADOR.Recordset
q The code behind the ADO data layer including how it works and how to invoke it
q How we integrate the code with MTS
q How to run this code from transactional ASP.
Hopefully the concepts covered in this chapter will help jump start development of your enterprise applications.
In this section we'll examine the ADO data layer from a high level in order to see the big picture. There are several aspects that we'll be delving into in this chapter including MTS, XML, ADO, VB, ActiveX servers and Transactional ASP. We'll keep the overview brief so we can jump right into the code.
So why should you create a data services layer that wrappers ADO? The reasons are numerous and compelling, as you'll soon see. Whether you're developing applications for the web or for a LAN, wrapping ADO will improve your architecture. So why is the ADO data layer such a powerful tool? Well, let's go over a few of the reasons that the ADO data layer can power your arsenal.
By building an ActiveX server that encapsulates all ADO query execution we are basically centralizing all data services code, resulting in a highly maintainable structure. This considerably simplifies the maintenance issues involved with making changes to query execution code because any changes we need to make to the code are all done in one place, no matter how many applications use it.
By building this ActiveX server to run under MTS, we increase the scalability of the code exponentially. Now, we can have an entire set of business rules for an application calling our ADO data layer. This single point of entry for the ADO calls can be run under MTS as an ActiveX server thus providing object pooling, database connection pooling and distributed transaction support (all inherent properties of MTS and COM+).
So what does this mean to us and why do we care? More and more application development is moving to the web. All of these applications need to gain access to a data source of some kind. Whether it is SQL Server, Oracle or an Exchange Email Server, data drives our applications. So when we have several applications running on a corporate intranet, for example, they all have to use ADO or some other mechanism to get to the data.
Now instead of worming ADO query execution code throughout each business objects in every one of our applications, we can centralize the data access into a single point of entry. This is great for enterprise solutions as this concept brings a uniform type of data access to all of our applications.
Furthermore, we want all of our applications to share the ADO data layer, so we run it under MTS and COM+. This way we can take advantage of MTS's features and reduce the number of objects running in memory and the number of open database connections at any one time. Basically, our applications are recycling to save valuable resources. All of these points help create an environment that fosters high scalability of concurrent users that is invaluable to enterprise applications. So basically, by using this data layer, we can increase the number of concurrent users and allow more applications to use the data layer.
Remember, COM+ is part of Windows 2000 and encapsulates COM, DCOM, MTS, and MSMQ under its roof.
Different calling applications may require data in different formats. For example, one calling application may require an ADOR.Recordset, but another calling application may not support this object (or any object, for that matter). Such situations often arise in a cross-browser web solution. In such cases, maybe an XML or two dimensional array might do the trick. As you will know from previous chapters, our ADO data layer can provide data in a variety of formats.
These days everybody is talking about how XML is going to change the world. Now I'm not going to dispute that position, because one thing is for sure: a cross-platform and universal data format can go a long way in bringing disparate systems together. We've got mainframes running DB2, Unix boxes running Oracle, Mac's, IMS, Exchange Servers, SQL Servers and many other types of data source. Linking all of these systems has always been an arduous task for developers. But things are changing. For instance, a mainframe application using DB2 can now output data in XML format. Then a web or LAN application can turn around and read that same XML file. Perhaps now we are starting to agree on a single data format to pass between these systems: XML.
We could pass our data around via XML to all of these systems and we finally would have the missing link that would bring the computing world together. Now, certainly XML won't solve world hunger, but no one can refute that XML is an upcoming technology that is rapidly gaining broad acceptance.
ADO confers on our data layer the ability to return XML.W e can add some pretty cool features to this wrapper object that really add value to enterprise applications
There are a few ways in which we can return the data via XML, as we'll discuss. For example, we can persist the resulting Recordset from the query to a Stream in the XML format. Then we can read that Stream and capture the XML in a string that we can pass back to the calling application. Alternatively, we can use the MSXML.DOMDocument object to create our own XML string that we can then return to the calling application. Both techniques have their advantages and disadvantages, as you'll see as we go through the code.
The MSXML component parses XML and, in order to manipulate XML documents, implements the W3C Document Object Model. Refer to the Appendix on XML for more information on XML's advantages and its role in n-tiered development
The main advantage to using ADO to persist a Recordset to XML is that it is quick and easy. However, the catch is that if we want to pass that XML around to other systems and then back, we need to ensure that the XML format is exactly the same as ADO expects. Not a big problem unless you want to deviate form ADO's XML format. I prefer to use my company's format for XML data as it suits our needs better. Because of this, I need to parse the XML myself to load it into a Recordset. I found this to be a small concession that returned much greater flexibility for my applications.
Let's consider this in a little more detail. When ADO saves a Recordset out to XML using the Save method, the format (the sets of tags and their names) of that XML is always the same. This is fine if we send a Recordset to XML and then back in. But we can't load a Recordset from an XML file that was not created by the ADODB.Recordset objects' Save method unless it has the same format. For example, see the XML samples below.
This first sample shows the XML as it was persisted by the ADODB.Recordset:

The second sample shows the XML as it was generated by hand. Notice the difference between their formats:
