www.tamertolba.4t.com

 

Chapter 8

Database Access Component

ActiveX server components extend your scripting capabilities by providing a reusable means of gaining access to information. For example, the Database Access component enables scripts to query databases. Thus, whenever you want to query a database from a script, you can use the Database Access component; you need not write complex scripts to perform this task.

The Database Access component uses ADO (ActiveXÔ Data Objects) to access information stored in a database or other tabular data structure. It also uses the connection pooling feature of ODBC 3.0 to make database access more efficient.

 

8.1 ODBC, OLE DB and ADO:

ODBC and OLE DB are Microsoft Windows® application programming interfaces (APIs) for accessing data. The older ODBC specification provides data access to primarily relational SQL-based databases, and it does this well. OLE DB, Microsoft's next-generation data-access specification, allows data access to a much broader set of data providers. Those providers include non-relational database systems, e-mail systems, and CAD/CAM data stores, as well as the classic relational database system.

OLE DB does not replace ODBC. In fact, OLE DB includes a data provider that allows you to use it with ODBC data sources. The important point to realize, however, is that Microsoft plans for OLE DB to go far beyond ODBC in providing universal access to data, no matter how or where it gets stored on the enterprise.

Where does ADO fit into this picture? ADO is a high-level interface to OLE DB. For now, you can conduct business as usual because you can use ADO to access OBDC data sources through OLE DB's ODBC data provider. In the future, however, you will be able to use ADO to access your e-mail system or some other non-relational data provider.

Microsoft has publicly stated that ADO eventually will replace the company's current myriad of data-access models, including DAO and RDO, so keep in mind that ADO is not just for Internet/intranet data access. ADO is the Microsoft data access model for the future!

 

8.2 Active Data Objects( ADO ):

The ADO component installed with Active Server Pages provides a simplified, high-powered data object model that enables you to access databases using an OLE DB provider, including the Microsoft ODBC provider. OLE DB is Microsoft's next-generation specification for data access.

The general idea of OLE DB is for data consumers (applications) to access a wide variety of data through service providers. OLE DB is based on the need to access and manipulate other forms of data besides relational databases using a native dialect (not necessarily SQL). If you want to retrieve spreadsheet cells from an Excel spreadsheet, you would use the service provider for Excel spreadsheets; for ODBC databases, you would use the ODBC database service provider. OLE DB is an API set that enables C++ developers to create data providers, service providers, and data consumers. ADO enables Visual Basic developers to use the OLE DB ODBC service provider to access and manipulate database. ADO resembles RDO and ODBC Direct in some ways, but it has a much simpler object

model, as The figure below shows.

 

To simplify scripting and programming, many of the ADO objects can be created independent of other objects. The Recordset object, for example, does not require the programmer to create a Connection object first (a loose object hierarchy). Using independent objects might seem a bit strange to an experienced DAO programmer, but once you get used to the ADO model, you will find it simple to use. By using ADO, you can create fully scrollable recordsets that can be updated. ADO supports the following features:

    1- Batch updates

     2- Stored procedures (including multiple recordsets)

     3- Free-threaded objects (see Chapter 23 for threading models)

     4- Various cursor types

     5- Recordset cache management

 

For a Visual Basic database Web developer, ADO provides one of the simplest methods to use database information across the World Wide Web.

Because ADO uses the OLE DB ODBC service provider, you can access any ODBC database to which your Web server has access. The only requirement for using a database with ADO on your IIS 3.0(or above) Web server is a system ODBC data source name (DSN). After the system DSN is added, you can use ADO to access the database.

 There are 3 top-level ADO objects that you need to be concerned with: The Command, Connection, and RecordSet objects.

 One of the coolest things about ADO is that when you use one of these objects, the other 2 are created automatically!  So, why have 3 to start with? Well, because each object has different properties, events, and methods, and from time to time you may want to do something with some of them. So, which object you invoke, how you use it, etc., are more or less dictated by what your needs are. So, let's start with a brief description of each object:

Connection object: You use the ADO Connection object to create a connection to a data provider. The ADO Connection object is similar to the DAO database object or the RDO rdoConnection object.

     Recordset object: You use the ADO Recordset object to create a set of records from a query. As in the DAO Recordset and the RDO rdoResultset objects, you can move forward and backward through ADO recordsets. Sometimes, ADO recordsets are called cursors. ADO recordset cursors are always built on the server.

·        Command object: You use the ADO Command object to point to SQL strings, stored procedures, or action queries that you can execute. The Command object is similar to the DAO QueryDef object or the RDO rdoPreparedStatement.

·        Errors collection: The ADO Errors collection allows you to loop through the collection of errors that may occur from a failed data-access attempt. Because one data-access statement may produce multiple errors, ADO defines the Errors collection rather than a single Error object. The ADO Errors collection is similar to the DAO collection of the same name and the rdoErrors collection.

 

8.3 Database Open:

Any ASP script that needs to connect to a database must open it on the server first.There are two ways:

     a connection via a DSN

     a DSNless connection

A DSN is the Data Source Name .

A DSN connection requires the server administrator setup a DSN on the server using the control panel, or, that you use a 3rd party ASP component so your ASP scripts can make the registry changes on the server to create their DSNs as needed.

1.At the computer running your Web server, open Control Panel.

2.Double-click the ODBC icon, and then click System DSN.

There are two types of data sources: User, which is available only to you, and System, which is available to anyone using the computer. Data sources for use with the Web server need to be of the System type.

3.Click Add, choose the Microsoft Access Driver, and then click Finish.

4.In the Data Source Name box, type student, and then click Select. Select the \AspSamp\Students\student.mdb file (in the Inetpub directory by default), and click OK.

5.Click OK to close the dialog boxes.

DSN connections generally at a minimum require a DSN name, user, and password. This line would open a DSN named "student" as a user named "student" with a password of "magic".

1   set conntemp=server.createobject("adodb.connection")

2   conntemp.open "DSN=Student; uid=student; pwd=magic"

3   set rstemp=conntemp.execute("select * from authors")

What if we didn't have a DSN? And we knew the name of the file (i.e. file based databases like Access, Paradox, FoxPro, etc.) or the name of the data source (SQLserver for example). Here is the way we could open a data source without a DSN! Note that you must know the actual filepath on the server, i.e.nwind.mdb is not good enough it needs to be "C:\thatserver\account17\ nwind.mdb". Fortunately the server.mappath function can turn a filename into the proper fully qualified filename with path on the server.

1   set conntemp=server.createobject("adodb.connection")

2   cnpath="DBQ=" & server.mappath("yourtable.mdb")

3   conntemp.Open "DRIVER={Microsoft Access Driver (*.mdb)}; " & cnpath

4   set rstemp=conntemp.execute("select * from authors")

Here is a sample connection to an access database named "nwind.mdb" in the root of the web site.

 

<HTML><HEAD>

<TITLE>nwind.asp</TITLE>

<body bgcolor="#FFFFFF"></HEAD>

<%

set conntemp=server.createobject("adodb.connection")

 

' DSNless connection to Access Database

DSNtemp="DRIVER={Microsoft Access Driver (*.mdb)}; "

DSNtemp=dsntemp & "DBQ=" & server.mappath("nwind.mdb")

conntemp.Open DSNtemp

' DSNless connection to Access Database

 

set rstemp=conntemp.execute("select * from customers where country='germany'")

howmanyfields=rstemp.fields.count -1

%>

<table border=1>

<tr>

<% 'Put Headings On The Table of Field Names

for i=0 to howmanyfields %>

       <td><b><%=rstemp(i).name %></B></TD>

<% next %>

</tr>

<% ' Now lets grab all the records

do  while not rstemp.eof %>

<tr>

<% for i = 0 to howmanyfields%>

       <td valign=top><%=rstemp(i)%></td>

<% next %>

</tr>

<% rstemp.movenext

loop

rstemp.close

set rstemp=nothing

conntemp.close

set conntemp=nothing%>

</table>

</BODY>

</HTML>

 

8.4 Accessing Data Using ADO:

The following ASP file (emp1.asp) uses ADO to grab a record from the Access 97

WebMeals.mdb database using the WebMeals ODBC system data source.

Following is the complete emp1.asp page:

<HTML>

                              <HEAD>

                              <TITLE>Emp1.asp Example</TITLE>

                              </HEAD>

                              <BODY>

                              <H1> Employee #1 </H1>

                              <%

                              ' Declare the variables

                              Dim rst

                              Dim varSQL

 

                              ' Create an empty recordset object

                              Set rst = Server.CreateObject("ADODB.Recordset")

 

                              ' Create the SQL statement and stick it in varSQL

                              varSQL = "SELECT * FROM qryCurrentEmployees " & _

                               "WHERE EmployeeID = 1"

 

                              ' Fill the recordset with records based on the

                              ' SQL statement in varSQL and the WebMeals

                              ' data source

                              rst.Open varSQL, "WebMeals"

 

                              ' Display the data

                              %>

                             <B>Name:</B> <%= rst("FirstName") %>

                               &nbsp; <%= rst("LastName") %>

                              <BR><B>Address:</B> <%= rst("Address") %>

                              <BR><B>City/State/Zip:</B> <%= rst("City") %>,

                               <%= rst("State") %>

                               &nbsp; <%= rst("ZipCode") %>

 

                              <%

                              ' Clean up the objects

                              rst.Close

                              %>

                             </BODY>

                              </HTML>

You can see the preceding code in action in Figure 2.

                

 

Figure 2: This page uses ADO code to extract a single record from the

qryCurrentEmployees query and display it on the Web page.

 

Note: If you want to run this example, you need to create a System data source

called WebMeals on your Web server machine that points to the WebMeals.mdb

database.

 

Pure HTML. The emp1.asp file seems as if it contains a lot of code, but it’s

actually quite simple if you break it down into several smaller parts. The first part of the ASP page is just pure HTML:

<HTML>

                                        <HEAD>

                                        <TITLE>Emp1.asp Example</TITLE>

                                        </HEAD>

                                        <BODY>

                                        <H1> Employee #1 </H1>

Declaring variables. In this stretch of code, I declare two variables. Remember

that all variables are variants in VBScript (the default ASP scripting language), so

you don’t find As Datatype in the VBScript Dim statement.

 

                        <%

                        ' Declare the variables

                        Dim rst

                        Dim varSQL

                           

 

Creating the Recordset object. You create the recordset in several steps:

 

1.Create an empty Recordset object:

 

Set rst = Server.CreateObject("ADODB.Recordset")

If you’re used to DAO or RDO in VBA, this way of creating objects may seem

strange. VBA allows you to early bind your objects — when you write your

code, you can set a reference to the object model’s type library. (Sometimes,

this reference gets created automatically.) You avoid having to use the

CreateObject function. Unfortunately, because the VBScript language

doesn’t support early binding, you must create all objects using the

CreateObject function.

 

You create ASP objects using the Server object, which provides access to

methods and properties of the Web server.

 

2.Add a SQL statement into the varSQL variable:

 

varSQL = "SELECT * FROM qryCurrentEmployees " & _

"WHERE EmployeeID = 1"   

 

For Access data sources, you can refer to both tables and queries in your

SQL statements.

 

3.Use the Recordset object’s Open method to fill it with the records

returned by executing the SQL statement from varSQL.

 

The second argument, in this example "WebMeals", tells ADO the name of

the data source to use:

 

                             rst.Open varSQL, "WebMeals"

 

                             %>   

 

Displaying the data. To display the data from the record returned by the

recordset, you must use a mixture of HTML and VBScript. The HTML provides the labels for the data; the VBScript provides the values from the recordset using the names of the fields from the Access query:

 

<B>Name:</B> <%= rst("FirstName") %>

&nbsp; <%= rst("LastName") %>

                        <BR><B>Address:</B> <%= rst("Address") %>

                        <BR><B>City/State/Zip:</B> <%= rst("City") %>,

                         <%= rst("State") %>

                         &nbsp; <%= rst("ZipCode") %>

                           

 

You can insert a nonbreaking space into your HTML by using the &nbsp; sequence of characters.

 

Clean-up time. The last section of code closes the Recordset object and ends

the HTML:

 

                        <%

                        rst.Close

                        %>

                        </BODY>

                        </HTML>

Now that wasn’t so bad, was it?

 

8.5 Flattening the Object Model:

In ADO, the object hierarchy has less emphasis. This means that, unlike DAO and

RDO, you don’t have to work your way down the object hierarchy just to create an

object. I took advantage of this fact in emp1.asp by directly creating the rst

recordset without first creating a connection.

What’s the advantage to this flatter object model? You have fewer lines of code

and less use of memory. I save a bit of memory because I avoid creating a

Connection object. Memory use is especially critical if dozens or even hundreds

of clients simultaneously use your Web page.

In many cases, however, you need to explicitly create a Connection object

because it’s more efficient when you perform multiple recordset or command

operations. Having the flexibility is nice, though.

Recordset options galore. The Open method of the Recordset object allows

you to create different kinds of recordsets. The syntax of the Open method follows:

recordset.Open source, activeconnection, cursortype, _

                             locktype, options

Source. The first argument of the Open method, Source, represents the source of

the recordset. In this case, I used an SQL string in emp1.asp, but I also could have

used the name of a table, or a server-stored procedure.

ActiveConnection. In the second argument, ActiveConnection, you can do one

of the following:

Use a connection string, which creates a new connection for the sole

purpose of creating the recordset.

Point to an active Connection object that you already created.

CursorType. You use the third argument, CursorType, to specify the type of

recordset to create. A summary of the possible values of this argument appears in

                        Figure 3.

Value

Constant
Description

0

  adOpenForwardOnly

Forward-only recordset cursor (the default)

1

adOpenKeyset

Keyset recordset cursor

2

adOpenDynamic

Dynamic recordset cursor

3

adOpenStatic

Static recordset cursor

 

 

                       

 

Figure 3: Possible cursor type values.

The default recordset cursor is a forward-only recordset. Unlike DAO recordsets,

you The different types of recordsets vary in how your recordset reflects changes made  by other users.

Changes to the records made by other users in static and forward-only recordsets

are invisible to you. That is, when you create a static or forward-only recordset, you are totally unaware of any changes made by other users. If you don’t need to move backward through the recordset, then use the forward-only recordset because it consumes less memory and is faster than the static cursor.

  Forward-only recordsets don’t support methods such as MovePrevious,

  MoveFirst, or MoveLast. Also, forward-only recordsets don’t support the use of

the RecordCount property.

The keyset recordset is very similar in behavior to the DAO dynaset. The number

of that other users make, nor do records deleted by other users disappear from your

recordset (although the deleted records become inaccessible). However, you do

get notification when existing records get updated.

 The dynamic recordset has no DAO counterpart. This type of recordset is totally

dynamic. When you have a dynamic recordset open, you get notices of recordset

additions, deletions, and updates. While the dynamic recordset is the most

functional, be aware that it’s also the most expensive in terms of memory and

speed.

LockType. The fourth argument specifies the type of locking to employ. A

summary of the possible lock types appears in Figure 4.

Value

Constant

Description

                         1

                                    adLockReadOnly

                                                            Read only

                         2

                                    adLockPessimistic

                                                            Pessimistic locking

                         3

                                    adLockOptimistic

                                                            Optimistic locking

                         4

                                    adLockBatchOptimistic

                                                            Optimistic locking with batch updates

 

 

                        Figure 4: Possible LockType values.

 

Set LockType to 1, read only, if you aren’t updating records.

 

Generally, if you’re updating records, you should set LockType to 3, optimistic

locking. All data providers support this type of locking. When you choose optimistic locking, the record locks only while ADO physically updates the record. In contrast, a Locktype of 2 provides pessimistic locking (if the data provider supports it). In this type of locking, the record locks while you edit the record. Some data providers may not offer pessimistic locking.

 

Setting the LockType argument to 4 tells ADO you want to employ batch updating.

This form of updating allows you to download multiple records, update them locally,  and submit them back to the data provider in a single batch. Many data providers  do not support batch updating.

 

Options. You use the optional Options argument to indicate the type of Source

argument you provided. You can set Options to any of the options in Figure 5.

 

                        

Value
Constant

Description

                         1

                                   adCmdText

                                                       Command text (SQL statement)

                         2

                                   adCmdTable

                                                       Table, view, or saved select query

                         4

                                   adCmdStoredProc

                                                       Stored procedure or saved action query

                         8

                                   adCmdUnknown

                                                       Unknown (the default)

 

 

Figure 5: Possible options values.

 

If you submit an SQL string as the Source argument, then set Options to 1.

 

If you set the Source argument to the name of a table, select query or view, then

you need to use a value of 2. Not all data providers allow you to use the

adCmdTable option.

 

If you want to call a stored procedure or saved action query, then you need to set

Options to 4.

By default, Options is set to a value of 8 (unknown). In this case, ADO attempts to

infer the source type from its contents.

 

Constants — what constants? The constants listed in Figures 3, 4, and 5 are

not predefined for you by VBScript as they are when you use ADO from VBA (with a reference to the ADO type library). You can use these constants in two ways in your code:

 

Define your own constants using these suggested names.

Include the file adovbs.inc "include" in your code. (If you use JavaScript, you

can include the file adojavas.inc include instead).

 

You can find these include files in the Program Files\Common Files\System\Ado

folder on your Web server. (Older versions of the Microsoft Web servers place

these files in the \Inetpub\wwwroot\ASPSamp\Samples folder.)

 

To incorporate an include file in your ASP file, use a server-side include statement

like the following:

 

<!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->

 

You need to place this preceding statement outside of any script. For example,

take a look at the next block of code:

                                                                                               

 

                            <%

                            Dim con

                            Dim rst

                            Dim strSQL

                            %>

                        <!--#include virtual="/ASPSAMP/SAMPLES/ADOVBS.INC"-->

                            <%

                            Set con = Server.CreateObject("ADODB.Connection")

 

If you need only a few constants, however, using the entire advobs.inc include file is probably overkill and wastes a lot of memory.

 

Another Recordset example. The emp1.asp example displays a single record

on the Web page. More typically, you want to display a group of records on a

single page using an HTML table — as shown in the second example, cust1.asp.

  The second example draws its records from the SQL Server version of the Meals

database.

 

Following is the complete ASP file:

                                                                                               

 

 

 

                             <HTML>

                             <HEAD>

                             <TITLE>Cust1.asp Example</TITLE>

                             </HEAD>

                             <BODY>

                             <H1> Our Customers </H1>

                             <%

                             ' Declare the variables

                             Dim con

                             Dim rst

                             Dim strSQL

                             ' Declare the Open method constants

                             Const adOpenStatic = 3

                             Const adLockReadOnly = 1

                             Const adCmdText = 1

 

                             ' Create a Connection object and point it to

                             ' the WebMealsSQL data source passing it

                             ' a username and password

                             Set con = Server.CreateObject("ADODB.Connection")

                             con.Open "WebMealsSQL", "WebUser", ""

 

                             ' Create the Recordset object and fill it with

                             ' the records from the SQL statement, using the

                             ' already established connection

                             ' Since this page is used to create an HTML table,

                             ' a static, read-only recordset is created

                             strSQL = "SELECT * FROM tblCustomers " & _

                              "ORDER BY LastName, FirstName"

                             Set rst = Server.CreateObject("ADODB.Recordset")

                             rst.Open strSQL, con, adOpenStatic, _

                              adLockReadOnly, adCmdText

                             ' Only display table if there are records

                             ' in the recordset

                             If Not rst.EOF Then

                               ' Display the header

                             %>

                               <TABLE BORDER>

                               <TR>

                                 <TD><B>Firstname</B></TD>

                                 <TD><B>Lastname</B></TD>

                                 <TD><B>City</B></TD>

                               </TR>

 

                             <%

                               ' Loop through the recordset until there

                               ' aren't anymore records

                               Do While Not rst.EOF

                                 ' Display the record values

                             %>

                                 <TR>

                                   <TD><%= rst("FirstName") %></TD>

                                   <TD><%= rst("LastName") %></TD>

                                   <TD><%= rst("City") %></TD>

                                 </TR>

                             <%

                                 ' If you forget this next statement,

                                 ' you'll keep printing the same record

                                 ' and create a very, very large table!

                                 rst.MoveNext

                               Loop

 

                             Else

                             %>

                               <B>No records in recordset!</B>

                             <%

                             End If

 

                             ' Clean up time

                             rst.Close

                             con.Close

                             %>

                             </TABLE>

                             </BODY>

                             </HTML>

 

You can see the preceding block of code in Figure 6 as it appears in Microsoft

Internet Explorer version 4.0.

 

Figure 6: This page uses ADO code to fill an HTML table with records from the

tblCustomers table.

Note: If you want to run this example, you need to create a System data source

called WebMealsSQL on your Web server machine that points to the WebMeals

SQL Server database. (Alternately, if you don’t have access to SQL Server you

could point this data source to the Access version of the Meals database instead.)

In the next few sections, I highlight some of the key pieces of code in cust1.asp.

Declaring variables and constants. After the requisite HTML header, the

VBScript code in cust1.asp declares its variables and several constants that the

Open method uses:

<%

                                        Dim con

                                              Dim rst

                                              Dim strSQL

                                              Const adOpenStatic = 3

                                              Const adLockReadOnly = 1

                                              Const adCmdText = 1

                                                 

Using constants in your VBScript code instead of arbitrary numbers is always a

good idea. This practice makes your code more readable.

 

Opening a connection. The following code from cust1.asp creates a

Connection object and opens it:

 

     Set con = Server.CreateObject("ADODB.Connection")

                              con.Open "WebMealsSQL", "WebUser", ""

                                 

 

 

Because the WebMealsSQL data source points to a SQL Server database, you

must provide username and password arguments. For Access databases, these

arguments are optional. If you’re using Access instead of SQL Server, you’ll need

to change the last line to:

con.Open "WebMealsSQL"

The first argument of the Connection object’s Open method, ConnectionString,

may refer to either an ODBC data source name (DSN) or a detailed ADO

connection string. All the examples in this paper use the former, but in some cases

you may need to provide further information. You need a detailed ADO connection

string when you’re using a non-ODBC data provider.

 

Creating the Recordset object. This section of code creates the Recordset

object using an SQL statement and links it up to the existing Connection object:

                                                                                               

 

                              strSQL = "SELECT * FROM tblCustomers " & _

                               "ORDER BY LastName, FirstName"

                              Set rst = Server.CreateObject("ADODB.Recordset")

                              rst.Open strSQL, con, adOpenStatic, _

                               adLockReadOnly, adCmdText

                                  

What if there aren’t any records? Cust1.asp includes the following If...Then

statement to handle the case where the query returns no records:

 

                                      If Not rst.EOF Then

                                       ' ...create the table ...

                                      Else

                                      %>

                                        <B>No records in recordset!</B>

                                      <%

                                      End If

                                         

The preceding code uses the EOF property of the Recordset object to check if

any records are present. If the query returns an empty recordset, ADO sets the

EOF property to True, otherwise it sets EOF to False.

 

Displaying the table. If you have records in the recordset (rst.EOF = True), then

you create the table header with this code:

                                                                                               

%>

                                           <TABLE BORDER>

                                           <TR>

                                             <TD><B>Firstname</B></TD>

                                             <TD><B>Lastname</B></TD>

                                             <TD><B>City</B></TD>

                                           </TR>

After you create the header, you need to loop through each of the records and plug

the FirstName, LastName, and City values into the rows of the HTML table. Do this by using a Do While loop and the MoveNext method of the recordset:

                                                                                               

 

                                   <%

                                     Do While Not rst.EOF

                                   %>

                                       <TR>

                                         <TD><%= rst("FirstName") %></TD>

                                         <TD><%= rst("LastName") %></TD>

                                         <TD><%= rst("City") %></TD>

                                       </TR>

                                   <%

                                       rst.MoveNext

                                     Loop

                                     

Don’t forget the MoveNext method. (Does this sound like a voice of experience

speaking?) If you do, then the Do While loop prints the same record in an infinite

loop, producing a Web page of infinite length — probably not what you intended.

 

8.6 Updating Data:

Using ADO, you can update records, add new records, and delete records. The

following sections demonstrate how to accomplish these feats with several

examples.

 

8.6.1 Adding records to a Recordset.:

To add a new record to an ADO recordset, you

use the AddNew and Update methods of a Recordset object. First, though, you

need to create a Recordset object. After you create a non-read-only recordset,

you’re ready to add a new record. The code to add a record should look something

like this:

rst.AddNew

                                                rst("field1") = value1

                                                rst("field2") = value2

                                                ' ...

                                              rst.Update

 

Adding a new record is always a three-step process:

 

                           1.Call the AddNew method to tell ADO you want to add a new blank record.

                           2.Set the values of one or more fields for the new record.

                           3.Call the Update method to save the new record to the database.

 

The next example consists of two files: an HTML file that captures a new record

using an HTML form (addcust1.html); and an ASP file (addcust1.asp) that adds the

new record to the tblCustomers table using the AddNew and Update methods.

Following is the addcust1.html file:

     <HTML>

                            <HEAD>

                            <TITLE>Addcust1.html Example</TITLE>

                            </HEAD>

                            <BODY>

                            <H1> Adding A New Customer </H1>

 

                            <FORM METHOD="POST" ACTION="Addcust1.ASP">

                            <TABLE>

                              <TR><TD>First Name:</TD>

                                  <TD><INPUT NAME="FirstName" SIZE=20></TD></TR>

                              <TR><TD>Last Name:</TD>

                                  <TD><INPUT NAME="LastName" SIZE=20></TD></TR>

                              <TR><TD>Address:</TD>

                                  <TD><INPUT NAME="Address" SIZE=40></TD></TR>

                              <TR><TD>City:</TD>

                                  <TD><INPUT NAME="City" SIZE=20></TD></TR>

                              <TR><TD>State:</TD>

                                  <TD><INPUT NAME="State" SIZE=6></TD></TR>

                              <TR><TD>ZipCode:</TD>

                                  <TD><INPUT NAME="ZipCode" SIZE=10></TD></TR>

                            </TABLE>

                            <BR><INPUT TYPE="SUBMIT" VALUE="Save Record">

                            <INPUT TYPE="RESET" VALUE="Reset Fields">

                            <BR><BR><A HREF="adomenu.html">Abandon edits

                            and return to home page</A>

                            </FORM>

                            </BODY>

                            </HTML>

 

  The addcust1.html page appears in Figure 7.

Figure 7: Adding a new record to the tblCustomers table.

 

And following is the addcust1.asp file that addcust1.html posts its data to:

                                                                                               

     <HTML>

                             <HEAD>

                             <TITLE>Addcust1.asp Example</TITLE>

                             </HEAD>

                             <BODY>

                             <H1> Adding A New Customer </H1>

                             <%

 

                             Dim con

                             Dim rst

                             Const adOpenKeyset = 1

                             Const adLockOptimistic = 3

 

                             ' Create the objects

                             Set con = Server.CreateObject("ADODB.Connection")

                             Set rst = Server.CreateObject("ADODB.Recordset")

 

                             ' Open the connection to the Meals database

                             con.Open "WebMealsSQL", "WebUser", ""

 

                             ' Create a keyset recordset based on the

                             ' tblCustomers table with optimistic locking

                             rst.Open "SELECT * FROM tblCustomers", con, _

                              adOpenKeyset, adLockOptimistic

 

                             ' Create a new blank record

                             rst.AddNew

 

                               ' Set the fields to the user-entered values

                               ' from the html form used to collect the data

                               rst("FirstName")= Request.Form("FirstName")

                               rst("LastName")= Request.Form("LastName")

                               rst("Address")= Request.Form("Address")

                               rst("City")= Request.Form("City")

                               rst("State")= Request.Form("State")

                               rst("ZipCode")= Request.Form("ZipCode")

 

                             ' Save the new record to the database

                             rst.Update

 

                             Response.Write "<B>Thank you!</B>"

 

                             rst.Close

                             con.Close

                             %>

                             <BR><A HREF="adomenu.html">Return to home page</A>

                             </BODY>

                             </HTML>

 

Because addcust1.asp needs to update data, I created a keyset recordset with

optimistic locking enabled:

 

rst.Open "SELECT * FROM tblCustomers", con, _

                                adOpenKeyset, adLockOptimistic

Values from the calling HTML form get sucked into the code using the Response

object, as in:

                                                                                                

                                 rst("FirstName")= Request.Form("FirstName")

 

When you successfully submit the new record, a confirmation page, addcust1.asp,

is displayed.

 

What about handling errors? The code in update1.asp assumes that the new

record is always successfully added to the tblCustomers table. Unfortunately, the

fact that the record was added at this point is not a foregone conclusion. Several

things can and will (from time to time) go wrong. For example, the update may fail

for the following reasons:

 

 You lack the correct permissions to update the records.

A field that doesn’t accept nulls is left blank.

You saved a string value to a numeric field.

You attempt to save a value that is too large for a field.

A check constraint (SQL Server) or a validation rule (Access) fails.

 

Always remember the one rule in computing: If something can go wrong, it will go

wrong — especially when you’re on vacation!

 

So what happens if you encounter an error while saving the record? The ASP

scripting engine prints an error to the page, as shown in Figure 8. The message

varies, depending on the type of error. No matter what the error, the result isn’t very professional looking.

                                                                                                

Figure 8: An error message as displayed by default.

 

VBScript error handling. Unlike its cousin VBA, VBScript has limited custom

error-handling capabilities. VBScript doesn’t support the use of procedure-level

error handlers. The error-handling capabilities of VBScript consist of the ability to

turn off the default error handling (which allows you to intercept the errors and

handle them yourself) with:

 

On Error Resume Next

and the ability to turn default error handling back on with

 

On Error GoTo 0

 

In addition, when you turn off the default error handling, you can use the VBScript

Err object to get information about the error. For example, you can check if an error has occurred with an If...Then statement like the following:

 

                                     If Err.Number <> 0 Then

                                       ' You know an error has occurred.

                                     End If

Whenever you check its value, Err.Number equals:

 

                             0 if no error has occurred, or

                             a long integer containing the error number of the error that has occurred

 

 You also have access to the error message that VBScript would have displayed.

You can find this message stored in the Description property of the Err object. You

can display the message with the following code:

 

                        Response.Write Err.Description

 

You must test the value of Err.Number immediately because Err.Number resets

after each statement and thus contains only information regarding the most recent

error.

 

The ADO errors collection. In addition to the VBScript Err object, the ADO

Connection object has an Errors collection that may contain multiple entries

many errors, if any, are in the collection. Thus, with code like this you can display all the errors that may have occurred from an ADO operation. (In the following

example, con points to an active ADO Connection object):

                                                                                               

varErrorCount = con.Errors.Count

                                If varErrorCount > 0 Then

                                    For varI = 0 To varErrorCount - 1

                                      Response.Write "<BR><I>" & _

                                       con.Errors(varI).Description & "</I>"

                                    Next

                                  End If

                                 

                                   

Which one should I use? Why use the ADO Errors collection when you can use

the simpler VBScript Err object? A particular ADO operation sometimes may

generate a series of errors. In these cases, the ADO Errors collection provides

additional information on the problem. In most cases, however, the VBScript Err

object and the ADO Errors collection return the same information, so you’re fine,

in most cases, if you use the simpler Err object.

 

No matter which form of error reporting you decide to use, you must use the

VBScript On Error Resume Next statement to tell VBScript you want to intercept

the errors that VBScript normally handles.

 

An error-handling example. If you decide to implement custom error handling in

your ASP pages, be prepared for a bunch of extra code. Because VBScript lacks

any way to define a procedure-level error handler, you need to check for the

occurrence of an error after every VBScript statement — or at least after every

VBScript statement that you think may cause an error.

 

One way to lessen the error-handling load is to create a function to take care of

some of the tedium of handling errors. I create such a function in a modification to

 the addcust1.asp file named addcust2.asp.

The HandleErrors function takes care of the error-handling in the following code:

                                                                                               

 

                               Function HandleErrors(varNum, varDesc)

                                 On Error Resume Next

                                 If varNum <> 0 Then

                                   Response.Write "<BR><B>The following " & _

                                    "error occurred:</B><BR>"

                                   Response.Write varDesc

                                   HandleErrors = 1

                                 Else

                                   HandleErrors = 0

                                 End If

                               End Function

 

                                  

 

 

 

 

 

The main code from addcust2.asp calls HandleErrors immediately after every

statement that may cause an error. For example, the code calls HandleErrors after

the Update method:

                                                                                               

rst.Update

                                 varErrors = varErrors + _

                                  HandleErrors(Err.Number, Err.Description)

The main code passes HandleErrors the error number and the description. I define

a variable, varErrors, to keep track of the number of errors that occurred. This

approach works because HandleErrors returns a 0 if no error occurs or a 1 if an

error occurs. At the end of the main code, I know whether the record addition

succeeded and I can display the status of the record addition to the user.

 

                               Response.Write "<BR><BR>"

                               If varErrors = 0 Then

                                 Response.Write "<B>Record added!</B>"

                               Else

                                 Response.Write "<B>Record could not be " & _

                                  "added because of errors!</B>"

                               End If

 

The same error that occurs in Figure 8 appears in Figure 9 using a custom

error-handling routine.

      

Figure 9: This error message is more professional looking and makes it clearer

that the record didn’t get added.

 

Going to the trouble of handling errors has two advantages:

 

You can display better, more user-friendly information to the user.

You can react to the error and branch in your code appropriately.

You don’t have to display the VBScript or ADO error message to the user. You can always check to see which error has occurred (using Err.Number) and then

display more user-friendly versions of some of the most common errors.

 

8.6.2 Updating a Record in a Recordset:

 

Unlike DAO and RDO, there is no Edit method of a recordset in ADO to indicate

when you want to begin editing a record. The code to edit a record should look

something like the following:

 

                                                rst("field1") = value1

                                                rst("field2") = value2

                                                ' ...

                                                rst.Update

                                                   

Editing a record is a three-step process:

 

                           1.Move to the record you want to edit.

                           2.Set the values of one or more fields for the record.

                           3.Call the Update method to save the changes to the database.

 

In fact, even Step 3 is optional. If you forget to use the Update method to save your

changes and move to another record, ADO automatically saves your edits for you.

Wow!

 

How then do you abandon your edits? Fortunately, ADO recordsets have a

method, CancelUpdate, which you can use to throw away your edits. Using the

CancelUpdate method can’t be easier:

 

                        rst.CancelUpdate   

 

I’ve created an example that you can use to update records in the tblCustomer

table of the SQL Server Meals database. This example uses three files:

 

Update.asp: This page displays a list of customers and lets you click on a

customer to edit the associated record.

UpdRec.asp: This page displays the current data from the customer record

using an HTML form and includes buttons to edit or delete the record.

UpdAct.asp: This page either saves the changes or deletes the record.

 

In this section, I discuss the updating portion of the example files. Later in this

paper, I discuss the delete functionality of the example files.

 

Update.asp. Much of the code in Update.asp is identical to the code from

cust1.asp. You can use the following section of code to display the values in a

standard HTML table:

                                                                                               

 <%

                               ' Loop through the recordset

                               Do While Not rst.EOF

                                 ' Display the record values

                             %>

                                 <TR>

                                   <!--Create a hyperlink in the left column

                                       that passes the CustomerId to the

                                       UpdRec.asp page                      -->

                                   <TD><A HREF="UpdRec.asp?CustomerId=

                                       <%= rst("CustomerId") %>">

                                       <%= rst("Name") %></A></TD>

                                   <TD><%= rst("City") %></TD>

                                   <TD><%= rst("State") %></TD>

                                 </TR>

                             <%

                                 ' Move to the next record

                                 rst.MoveNext

                               Loop

                              

The only way the preceding code differs from the code in cust1.asp is the part that

creates the first column of the table. The preceding example uses the <A> tag to

create a hyperlink that displays the customer’s name from the Name field, but sets

up a hyperlink to UpdRec.asp, passing this page the string "CustomerId=" and the

value of the CustomerId for that record.

 

This sends HTML to the browser that looks like the following (for the record with a CustomerId = 7):

 

                        <A HREF="UpdRec.asp?CustomerId=7">Alicia Brown</A>   

 

Take a look at Figure 10 to see how update.asp appears in Netscape Navigator.

                                                                                               


 

                        Figure 10: The Update.asp page lets you select any customer for updating.

 

UpdRec.asp. The code behind UpdRec.asp is responsible for displaying the

values from the requested record, as well as two submit buttons that determine the

action to take on the record.

 

  Following is the complete UpdRec.asp file:

 

                       <HTML>

                       <HEAD>

                       <TITLE>UpdRec.asp Example</TITLE>

                       </HEAD>

                       <BODY>

                       <H1> Customer Record Update Page </H1>

                       <%

                       ' Declare the variables

                       Dim con

                       Dim rst

                       Dim strSQL

                       ' Declare the Open method constants

                       Const adOpenStatic = 3

                       Const adLockReadOnly = 1

                       Const adCmdText = 1

 

                       ' Create a Connection object and point it to

                       ' the WebMealsSQL data source

                       Set con = Server.CreateObject("ADODB.Connection")

                       con.Open "WebMealsSQL", "WebUser", ""

 

                       ' Create a recordset with one record in it

                       ' based on the CustomerId passed to this page

                       ' from the update.asp page

                       strSQL = "SELECT * FROM tblCustomers " & _

                        "WHERE CustomerId =" & Request("CustomerID")

                       Set rst = Server.CreateObject("ADODB.Recordset")

                       rst.Open strSQL, con, adOpenStatic, _

                        adLockReadOnly, adCmdText

 

                       ' Only display form if there is a matching

                       ' record

                       If Not rst.EOF Then

                       %>

                       <FORM METHOD="POST" ACTION="UpdAct.ASP">

                         <INPUT Type="HIDDEN" NAME="CustomerId"

                         Value="<% = rst("CustomerId") %>">

                       <TABLE>

 

                         <TR><TD>CustomerId:</TD><TD>

                         <B><I><% = rst("CustomerId") %></I></B>

                         </TD></TR>

 

                         <TR><TD>First Name:</TD><TD>

                         <INPUT NAME="FirstName"

                         Size=20 Value="<% = rst("FirstName") %>">

                         </TD></TR>

 

                         <TR><TD>Last Name:</TD><TD>

                         <INPUT NAME="LastName"

                         Size =20 Value="<% = rst("LastName") %>">

                         </TD></TR>

 

                         <TR><TD>Address:</TD><TD>

                         <INPUT NAME="Address"

                         Size=40 Value="<% = rst("Address") %>">

                         </TD></TR>

 

                         <TR><TD>City:</TD><TD>

                         <INPUT NAME="City"

                         Size =20 Value="<% = rst("City") %>">

                         </TD></TR>

 

                         <TR><TD>State:</TD><TD>

                         <INPUT NAME="State"

                         Size =6 Value="<% = rst("State") %>">

                         </TD></TR>

 

                         <TR><TD>ZipCode:</TD><TD>

                         <INPUT NAME="ZipCode"

                         Size =10 Value="<% = rst("ZipCode") %>">

                         </TD></TR>

                       </TABLE>

                       <BR><INPUT TYPE="SUBMIT" Name="Submit"

                            VALUE="Save Changes">

                           <INPUT TYPE="SUBMIT" Name="Submit"

                            VALUE="Delete Record">

                       </FORM>

 

                       <%

                       Else

                       %>

                         <B>No record was found matching this CustomerID!</B>

                       <%

                       End If

 

                       ' Clean up time

                       rst.Close

                       con.Close

                       %>

 

                       <A HREF="update.asp">[Abandon edits and select another customer]</A>

                       &nbsp;&nbsp;

                       <A HREF="adomenu.html">[Return to home page]</A>

                       </BODY>

                       </HTML>

 

The preceding page creates a recordset based on the CustomerId value passed

to the page by the update.asp page. Following is the SQL for the recordset:

 

 

                               strSQL = "SELECT * FROM tblCustomers " & _

                                "WHERE CustomerId =" & Request("CustomerID")

The following statement sets up the form to post its data to the UpdAct.asp page

when the user clicks the Submit button:

                                                                                               

<FORM METHOD="POST" ACTION="UpdAct.ASP">

 

The form displays the CustomerId value as regular HTML text rather than as a form field to prevent the user from changing it. I also include, however, a hidden control on the form that contains the CustomerId value so it can be passed along to the UpdAct.asp page:

                                                                                                

                                    <INPUT Type="HIDDEN" NAME="CustomerId"

                                    Value="<% = rst("CustomerId") %>">

 

A good way to pass along information between pages is to store it in hidden

controls.

 

The UpdRec.asp page contains two Submit buttons. Because I include Name

subtags for both Submit buttons and give them the same name — in this example

Submit (but there’s nothing special about this name) — the name and value pair

post to UpdAct.asp (see Figure 11). Thus, the code in UpdAct.asp can tell which

button the user clicks. This trick doesn’t work unless you include the Name subtag

in the Submit button tags.

                                                       

Figure 11: You can edit a customer record using the UpdRec.asp page.

 

UpdAct.asp. The UpdAct.asp page completes the update operation by opening a

recordset based on the edited record from UpdRec.asp and saving the updated

values back to the record. Much of this code is similar to the two other pages, so in

this section I highlight only key portions of the code.

 

In this portion of code from UpdAct.asp, the LockType argument of the rst.Open

method is set to adLockOptimistic to allow for editing:

 

 

                                    rst.Open strSQL, con, adOpenStatic, _

                                     adLockOptimistic, adCmdText

 

The following If...Then statement determines which of the Submit buttons on

UpdRec.asp the user clicked:

                                                                                               

                                 If Request("Submit")= "Save Changes" Then

                                    

 

 

The updated values carry over from UpdRec.asp, and the Update method saves

the changes to the database in this stretch of code:

                                                                                                

 

  rst("LastName") = Request("LastName")

                                   rst("FirstName") = Request("FirstName")

                                   rst("Address") = Request("Address")

                                   rst("City") = Request("City")

                                   rst("State") = Request("State")

                                   rst("ZipCode") = Request("ZipCode")

                                   rst.Update

                                   

8.6.3 Deleting a Record from a Recordset:

 Deleting a record in ADO is pretty simple. You use the Delete method of the

Recordset object to delete the current record. The code looks like the following:

 

rst.Delete   

 

Deleting a record is a two-step process:

 

                           1.Move to the record you want to delete.

                           2.Call the Delete method to delete the record from the database.

 

Following is the code in UpdAct.asp that deletes the record:

                                                                                                

 

                                If Request("Submit")= "Save Changes" Then

                                   '...

                                 Else

                                   ' Delete record

                                   rst.Delete

                                   '...

                                 End If

 

 

 

8.7-Error Trapping Database Code :

Ex.

First add some error code to the script to display the messages and

bad SQL that causes the problem, for example:

 

<%

on error resume next

...

Set Conn = Server.CreateObject("ADODB.Connection")

...

  

SQLstmt = "..."

Set RS = Conn.Execute(SQLStmt)

If err.number>0 then%>

  VBScript Errors Occured:<P>

  Error Number=<%=err.number%><P>

  Error Descr.=<%=err.description%><P>

  Help Context=<%=err.helpcontext%><P>"

  Help Path=<%=err.helppath%><P>

  Native Error=<%=err.nativeerror%><P>

  Source=<%=err.source%><P>

 SQLState=<%=err.sqlstate%><P>

<%else%>

  

  No problems occured!<p>

<%end if

IF conn.errors.count> 0 then%>

  Database Errors Occured<P><%=SQLstmt%><P>

  <%for counter= 0 to conn.errors.count%>

      Error #<%=conn.errors(counter).number%><P>

      Error desc. -><%=conn.errors(counter).description%><p>

  <%next

else%>

   Everything Went Fine

<%end if

Conn.Close%>

  

8.8 Examples :

 8.8.1 The .maxrecords property:

This example demonstrates the capabilities how to display a table from a SQL statement but limit the output to a specific number of

records.

 

<html><head>

<TITLE>dbmaxrecs.asp</TITLE>

</head><body bgcolor="#FFFFFF">

<!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->

  

<%

set rstemp=Server.CreateObject("adodb.Recordset")

rstemp.maxrecords=15

connectme="DSN=Student;uid=student;pwd=magic"

rstemp.open "select * from titles", _

       connectme,adopenstatic

' table display

howmanyfields=rstemp.fields.count -1

%>

<table border=1><tr>

<%

for i=0 to howmanyfields %>

       <td><b><%=rstemp(i).name %></B></TD>

 

<% next %>

</tr>

<%

do  while not rstemp.eof %>

<tr>

<% for i = 0 to howmanyfields%>

       <td valign=top><%= rstemp.fields(i).value %>&nbsp;</td>

<% next %>

</tr>

<%

rstemp.movenext

loop

%>

</table></body></html>

  

8.8.2 Paged Table Displays

This example demonstrates the capabilities how to retrieve a recordset divided up into pages, and to only select data from a specified page. It does not in any way store a recordset or connection in memory when the page is not accessed unlike many solutions you will read about. The ADO properties that make this magic possible are .AbsolutePage, .PageCount and .PageSize.

 

<html><head>

<TITLE>dbtablepaged.asp</TITLE>

</head><body bgcolor="#FFFFFF">

 

 <!--#INCLUDE VIRTUAL="/ADOVBS.INC" -->

<%

mypage=request.querystring("whichpage")

If  mypage="" then

   mypage=1

end if

mypagesize=request.querystring("pagesize")

If  mypagesize="" then

   mypagesize=10

end if

set rstemp=Server.CreateObject("ADODB.Recordset")

connectme="DSN=Student;uid=student;pwd=magic"

  

sqltemp="select * from publishers"

rstemp.cursorlocation=aduseclient

rstemp.cachesize=5

rstemp.open sqltemp,connectme

rstemp.movefirst

rstemp.pagesize=mypagesize

maxcount=cint(rstemp.pagecount)

rstemp.absolutepage=mypage

howmanyrecs=0

howmanyfields=rstemp.fields.count -1

response.write "Page " & mypage & " of " & maxcount & "<br>"

%>

  

<table border=1><tr>

<% 'Put Headings On The Table of Field Names

for i=0 to howmanyfields %>

       <td><b><%=rstemp(i).name %></B></TD>

<%next%>

</tr>

<%do while not rstemp.eof and howmanyrecs<rstemp.pagesize%>

<tr>

<%for i = 0 to howmanyfields%>

       <td valign=top><%=rstemp(i)%></td>

<%next%>

</tr>

<%

 

rstemp.movenext

howmanyrecs=howmanyrecs+1

loop

rstemp.close

set rstemp=nothing

%>

</table><p>

<%

pad="0"

scriptname=request.servervariables("script_name")

for counter=1 to maxcount

   If counter>=10 then

      pad=""

   end if

  

ref="<a href='" & scriptname & "?whichpage=" & counter

   ref=ref & "&pagesize=" & mypagesize & "'>" & pad & counter & "</a>"

   response.write ref & " "

   if counter mod 10 = 0 then

      response.write "<br>"

   end if

next

%>

</body></html>