Subscribe to SQL Server Magazine | See More Active Server Pages (ASP) Articles Here | Reprints | Or get the Monthly Online Pass—only $5.95 a month!
DOWNLOAD THE CODE:
Download the Code 15986.zip

Data-access code is usually the foundation to building any Web application. Developers typically write ADO code that uses either the Command or Recordset object and sets various properties. Then, the code either executes a SQL statement or calls a stored procedure. Creating this code in each script is time-consuming and error-prone, so I was delighted when Microsoft recently sent me a new include file that provides a standard set of data-access functions that you can use from any Active Server Pages (ASP) application.

Microsoft has stress-tested this include file as part of its benchmarking efforts, and the code is fast and reliable. You can use these functions any time you need to execute a SQL statement, run a stored procedure, or create an ADO Recordset object from a database. The functions in the include file will streamline your script code and make writing data-access applications much easier.

In the Include File
Let's look at the database functions in the support file, ADOHelper, and see how it uses them. This file contains the functions that provide the ADO database support. The file, adohelper.asp, as Listing 1 shows, implements a VBScript class using the Class statement, which creates a class named ADOHelper. Your application can invoke ADOHelper as if it were a COM object.

Class ADOHelper

At the end of the file, an End class statement terminates the class.

End class

Other than these two statements, adohelper.asp is traditional VBScript. In fact, you could remove the Class statements and use ADOHelper as a normal include file. Using the code as a class makes the code more intuitive because in your script you can see that you're using a method from the class. However, if you don't want to use the code as a class and just want to call the functions, you can remove the Class statements. The choice is yours.

ADOHelper contains several functions—methods in object speak—that implement the class's database features. The first function is GetConnectionString, which returns the connection string used to access your application. You must change this function's connection string information to match the names of your server and database and the required login information.

Four other key functions in the include file begin with Run, each executing either a SQL statement or a stored procedure. Table 1 describes the Run functions. The two RunSP functions accept the same three parameters. The first parameter is the name of the stored procedure you want to execute. The second is the name of an array containing the stored procedure's input parameters and their criteria. The third is the name of a variable that will contain any output parameters that the stored procedure generates.

All four Run functions have similar code; for example, the following is the code for RunSP.

Function RunSP(ByVal strSP, params, byRef OutArray)
   Dim cmd, OutPutParms
	Set cmd = Server.CreateObject("adodb.Command")
   cmd.ActiveConnection = GetConnectionString()
	cmd.CommandText = strSP
	cmd.CommandType = adCmdStoredProc
	collectParams cmd, params, OutPutParms
   cmd.Execute , , adExecuteNoRecords
	if OutPutParms then OutArray = collectOutputParms
(cmd, params)
        Set cmd.ActiveConnection = Nothing
	set cmd = Nothing
	RunSP = 0
End Function

The RunSP function contains two noteworthy pieces of code: the collectParams function and the adExecuteNoRecords parameter. Various scripts use the collectParams function to build the ADO parameters collection. Setting up the parameters for a stored procedure call is perhaps the most trying part of using stored procedures. The collectParams function simplifies the process of creating and using parameters with a stored procedure and makes setting them up a non-issue.

RunSP also uses the adExecuteNoRecords parameter on the cmd.Execute line. This parameter tells ADO that the requested action doesn't need a recordset. Using this parameter usually gives your application a performance boost because ADO and the database will have less work to do.

Using the File
Using the adohelper.asp file from your ASP scripts requires a couple of steps.

  1. My version of adohelper.asp uses several ADO constants that the file doesn't define. Instead of defining these constants in the ASP file, my code gets them from the ADO type library. To use the type library from your .asp script, put the following line in the global.asa file:
  2. This line links the ADO type library into your application. You can create this link automatically in Microsoft Visual InterDev by going to the Project menu, Project References, and selecting the proper reference, as Figure 1 shows.

  3. You can include adohelper.asp in any .asp files where you'll use its features; place a link similar to the following one in your .asp file:

As a relative link (without a path), you must adjust the link based upon the configuration of your application directories.

After you have taken these two steps, you can use the include file's features. Listing 2 shows my code for ListAuthor.asp, which calls the retrieveauthors stored procedure to obtain a recordset of all authors from the Pubs database. (Note: This code isn't a standard part of the Pubs database.)

  • The code at Callout A in Listing 2 defines the variables used in the script.
  • The code at Callout B in Listing 2 creates an instance of the ADOHelper class. Then, the code sets two variables: the variable containing the stored procedure name (sSQL) and the variable containing the parameters for the stored procedure (sParams). In Listing 2, the stored procedure requires no parameters, so the variable is set to zero.
  • The code at Callout C in Listing 2 executes the RunSPReturnRS method. The rest of the code in Listing 2 loops through the recordset and outputs values from it to the HTML stream using Response.Write.

So far, we've used the stored procedures by setting a couple of variables and executing one function. Not bad! That's the beauty of this include file.

In a slightly more complex case, Listing 3 shows my code for ShowAuthor.asp. This code also executes the RunSPReturnRS but to execute the RetrieveAuthor stored procedure. (This code isn't a standard part of the Pubs database either.) RetrieveAuthor requires one parameter: the author id (au_id). The code at Callout A in Listing 3 sets the data for this parameter and stores it in the sParams variable.

The line that sets the sParams variable looks strange because it calls the Array function twice. First, the function sets up the array of parameter arrays; then, each parameter calls the function once. The result is an array of parameters, with each parameter having four entries. A more complex stored procedure call from another application shows how the array of parameter arrays works.

Set rs = db.RunSPReturnRS("Add_CartItem", Array( _
Array("@SessionID", adInteger, AdParamInput,4, CLng(group)), __
  Array("@BookID", adInteger, AdParamInput, 4, bookID), _
     Array("@Author", adVarChar, AdParamInput, 50, author), __
     Array("@Title", adVarChar,  AdParamInput, 50, title),  _
     Array("@Price", adCurrency, AdParamInput, 8, price), _
	  Array("@Qty", adInteger,  AdParamInput, 4, Qty)), 
          OutArray)

Six Array statements are nested in the first array, and each of the subarrays sets one parameter. To get the parameters' values, I use the Data View window in Visual InterDev as I build the application. Data View lets me inspect the tables and stored procedures. Then I can look at each parameter's properties and use them to set or pass the parameter definitions.

Faster and More Reliable
Standardized code is one of the best ways to make your application run faster and more reliably. Using functions such as those in adohelper.asp also speeds up the development process because you don't need to recreate or repeat ADO code each time you touch the database.

End of Article




Post Your Comments Here

You must be a registered user or online subscriber to comment on this article. Please log on before posting a comment. Are you a new visitor? Register now

Reader Comments

Your "printer-friendly" version of the following page doesn't reformat most of the text lines. The printed page (even in landscape mode) on an 8 1/2 inch x 11 inch sheet of paper prints only 2/3 of each printed line.

http://www.sqlmag.com/Articles/Print.cfm?ArticleID=15986

John Colbert

To Webmaster,

FYI. I used the printer-friendly to print this document(no.=15986) but the printed document is run over the margin.

Lawrence

Lawrence Ho

The class construct in scripts definitely offers an excellent vehicle for encapsulation, and promotes intuitive, standardized and reusable code. However, it's been my experience that VBS class code doesn't perform well enough to be used in high-availability applications.

Accessing a class "property" takes about 50% longer than accessing a regular variable (with get and put methods, up to 3 times as long.) And class member function call overhead is also appreciably greater than that of ordinary sub/function calls.

So while I agree with almost everything presented, I have to take exception with the claim that it's any faster at all. Because I've tested VBS classes exhaustively within the last 3 months, and I submit to you that it isn't even as fast, not even close.

-Mark McGinty

Mark McGinty

Does anyone know how to "retrive multiple recordsets from a single execution" ? I keep getting this error message all the time when using rs.NextRecordset

Michael

This seems to work great for stored procs returning a single record set, but by utilizing the Server.CreateObject("adodb.Recordset") I get the following error when running stored procedures that return multiple record sets -- "ADODB.Recordset (0x800A0CB3) Current provider does not support returning multiple recordsets from a single execution." Also, it gives me fits when I use the adParamReturnValue for the SQL Server RETURN value so I have gone back to the my previous way of calling stored procs using just the Command object until I find a way around all this. If anyone knows ways around these issues, please inform me.

Matt Stoddard

Excellent article, but the "printer-friendly" option isn't. When used to print the right side of the document is chopped off. The only way I could print a copy that wasn't butchered was to copy into WORD.

Please let you web-master know he has some work to do.

alan spillert

In the function Begin Callout B What is Callout? Is it a reserve word?

jd

This is very helpful. However, there are two serious issues in this article: hard-coding SQL Server server name (this prevents portablility of code) and hard-coding the userid and password account (this is a security risk). To minimize this, consider using an ODBC source to mask the SQL Server server name and database name. Also consider using a resource file that has the userid and password separate from the code so that if there is a security breach, the userid and password can be changed with NO recoding. If possible, use NT Authentication (if so appropriate) that would eliminate the need for a specific userid and password.

Just suggestions from experience.... Thanks.

Eddy White

This is a real time saver.....but what about sql-server generated errors?

alan scott

This code is from the "Nile" example at MSDN, I'v been working with it for some time (it closely resembles the VB, COM+ Data Access Layer from the "Fitch & Mather 2000" example at MSDN too)

This code has a few issues: 1) The line err.raise m_modName, "collectParams(...): incorrect # of parameters" Is a leftover form the COM+ port and can't be run

2) In the method "RunSPReturnRS" The line: Set rs.ActiveConnection = Nothing (sometimes ? allways?) gives an error that you can't modify a connection that belongs to a command object (I haven't found the cause of this yet)

3) The collectParams method does not support "Image" parameters (or "Memo" in access).

But it's good for building a standardised Data Access Layer and can easily be turned into a VB Com+ component (allthough you might want to get the already ported VB COM+ component from the "Fitch & Mather 2000" example at MSDN :-)

Kind Regards, Allan Ebdrup, 10-4 ApS

Allan Ebdrup

Great, but I'm looking for the "return value" (adParamReturnValue) as result of the execution of the SP...

Claudio Basso

Could you please supply the stored procedures needed in the samples?

Running the samples results in errors like this: Fejltype: Der opstod en Microsoft VBScript-kompileringsfejl (0x800A0401) Slut på sætning var ventet /pubs/ShowAuthors.asp, line 31, column 14 Begin Callout A -------------^

The statement is not legal to IE. What is the problem ?

Best regards, Bo Hansen

Bo Hansen

This article is a blatant ripoff of the DBHelper class used in the FMStocks Microsoft application.

dave

how to use precision

rajinikanth

 
 

ADS BY GOOGLE