Now that we have a viable ActiveX server running under MTS, we need an application to invoke it. We'll use an ASP application, although we could use an application written in VB, VC++, or even written in VBScript within Internet Explorer using RDS. Just remember that although we're concentrating on ASP, the concept is the same for all of these environments.
The GetAuthorUsingSQL.asp file is an ASP that will invoke our ActiveX server and return the data from a query we specify. We'll ask it to get a list of authors, from the SQL Server pubs database, with a last name beginning with the letter "G". So, let's jump into the code to get a closer look.
We'll use this file to store the enumerator values from our BlueSand_DataLayer project as constants for our ASP web application. Notice we simply translate the values from the BlueSand_DataLayer to a form that ASP understands. We'll include this file in our GetAuthorUsingSQL.asp file:
<%
'-----------------------------------------------------------------------------
'--- Database provider types
'-----------------------------------------------------------------------------
Const eDBProviderAccess = 1
Const eDBProviderSQLServer = 2
Const eDBProviderOracle = 3
'-----------------------------------------------------------------------------
'-----------------------------------------------------------------------------
'--- Data Stream types
'-----------------------------------------------------------------------------
Const eDataStreamRecordset = 0
Const eDataStream2DArray = 1
Const eDataStreamXML = 2
'-----------------------------------------------------------------------------
%>
As you can see from the following code, to start the ASP that invokes our ActiveX server we include the DataLayerEnums.inc file that we've just seen and we declare all of our variables. Notice that the first line of code also defines that this page will employ the Transaction setting of Required. So what does this mean? It means that this page will begin a transaction under MTS. It also means that any objects created by this page that run under MTS will be asked to join the ASP's transaction. Since our C_Data_ADO_MTS class has an MTSTransactionMode of UsesTransactions, if we invoke that class from this ASP, it will join the transaction. On the other hand, if we remove the Transaction="Required" code from the ASP, there would no longer be a transaction for our C_Data_ADO_MTS class to join.
<%@ Language="VBScript" Transaction="Required"%>
<%Option Explicit%>
<!-- #include file="DataLayerEnums.inc" -->
<%
'-----------------------------------------------------------------------------
'--- Declare all variables
'-----------------------------------------------------------------------------
Dim lDataStreamType 'As Long
Dim oData 'As BlueSand_DataLayer.C_Data_ADO_MTS
Dim oLogonParms 'As BlueSand_DataLayer.C_LogonParameters
Dim sAuthorLastName 'As String
Dim sDatabaseName 'As String
Dim sDataSource 'As String
Dim sPassword 'As String
Dim sSQL 'As String
Dim sUserID 'As String
Dim vData 'As Variant
'-----------------------------------------------------------------------------
Next, we set the properties that define how to access our data source along with our "last name" parameter. We also set the lDataStreamType variable to the eDataStreamXML constant. We'll pass this into the ExecuteSQL method of the C_Data_ADO_MTS object to indicate that we want our data and metadata to be returned as XML.
'-----------------------------------------------------------------------------
'--- Set the connection properties
'-----------------------------------------------------------------------------
lDataStreamType = eDataStreamXML
'lDataStreamType = eDataStream2DArray
'lDataStreamType = eDataStreamRecordset
sDataSource = "dimaggio"
sDatabaseName = "pubs"
sUserID = "sa"
sPassword = ""
sAuthorLastName = "G"
'-----------------------------------------------------------------------------
Next, we create an instance of the BlueSand_DataLayer.C_Data_ADO_MTS class under MTS. We then use that object to create a C_LogonParameters object, with all of its properties set, which we will pass into the ExecuteSQL method. We also specify our SQL statement here, which indicates that we want retrieve all authors with the last name beginning with the letter "G".
'-----------------------------------------------------------------------------
'--- Prepare the Logon Parms and SQL
'-----------------------------------------------------------------------------
Set oData = Server.CreateObject("BlueSand_DataLayer.C_Data_ADO_MTS")
Set oLogonParms = oData.CreateLogonParameters(CStr(sUserID), _
CStr(sPassword), _
eDBProviderSQLServer, _
CStr(sDataSource), _
CStr(sDatabaseName), _
CLng(30))
sSQL = "select * from authors where au_lname like '" & sAuthorLastName & "%'"
'-----------------------------------------------------------------------------
Now we get to run the SQL query and retrieve the XML we requested. The following ASP code evaluates the type of data we requested and executes the BlueSand_DataLayer.C_Data_ADO_MTS object's ExecuteSQL method accordingly. Notice that, in the case where we request XML, we set the ContentType of the page to be XML and then we simply write the return value of the ExecuteSQL method to the browser:
'-----------------------------------------------------------------------------
'--- Execute the SQL and determine how to return the data.
'-----------------------------------------------------------------------------
Select Case lDataStreamType
Case eDataStreamRecordset
Set vData = oData.ExecuteSQL(oLogonParms, sSQL, eDataStreamRecordset)
Case eDataStream2DArray
vData = oData.ExecuteSQL(oLogonParms, sSQL, eDataStream2DArray)
Case eDataStreamXML
vData = oData.ExecuteSQL(oLogonParms, sSQL, eDataStreamXML)
Response.ContentType = "text/xml"
Response.Write vData
End Select
'-----------------------------------------------------------------------------
%>
Now that we have all the tools in place, let's kick this application off. When we browse to this ASP, we'll see the resulting XML from the ExecuteSQL method.

As you can see, it is easy to run this code and it is quite extensible as we can use it from any COM compliant application.
Let's take a look now at how the ActiveX server reacts to our invocation of it. Go back to the Component Services window and expand the DataLayer package's Components node. Then, position the window so that we can see the "marbles" (the icons that represents our components) and the Internet Explorer browser at the same time:

Got it? Good. Now, click the Refresh button on the browser and watch the marbles spin! If your marbles don't spin, you can right-click the DataLayer package and select the Shut Down menu option. This will empty the object pool in the package so that it takes longer for the objects to start up. Why do this? Simply because it will make the marbles spin long enough for us to see them. If the object already exists in the pool, we may not see them spin as it may happen faster than Windows refreshes the page. Also, notice that the call times start out being a few seconds long for the first object's creation. Then, the subsequent object activations all take merely a few milliseconds. So what's happening here? When we see the marbles spin the first time (on the first call), we are watching MTS create the object instances for the first time. Then, when subsequent calls are made, the objects are already created and in the MTS pool, so MTS doesn't have to create them. Instead, MTS uses these created object instances and just re-activates them for use. Why don't we see the marbles spin after the first time? When MTS re-activates the object instances, it happens so fast that we don't see them spin. As we can see, the power of MTS is evident when we look at it through this portal.