ActiveX 数据对象 (ADO) 是一种既易于使用又可扩展的技术,用于向网页添加数据库访问。可以使用 ADO 编写简洁和可扩展的脚本,连接到与 OLE DB 兼容的数据源,如数据库、电子表格、顺序数据文件或电子邮件目录。OLE DB 是一个系统级的编程接口,它提供一套标准的 COM 接口,用来展示数据库管理系统的功能。使用 ADO 的对象模型,您可以轻松地(使用 VBScript 或 JScript 等脚本语言)访问这些接口,并将数据库功能添加到您的 Web 应用程序中。另外,您还可以使用 ADO 访问与开放式数据库互连 (ODBC) 兼容的数据库。
如果您是一位对数据库互连知识有一定了解的脚本编写者,您将发现 ADO 的命令语法很简单,而且易于使用。如果您是一位经验丰富的开发人员,您将非常欣赏 ADO 为各种数据源提供的这种可扩展的、高性能访问。
有关 ADO 的详细信息,请访问 Microsoft Universal Data Access (UDA) 网站。
创建 Web 数据应用程序的第一步是为 ADO 提供一种定位并标识数据源的方法。这一步通过“连接字符串”实现。连接字符串是一系列用分号分隔的参数,用于定义诸如数据源提供程序和数据源位置等参数。ADO 使用连接字符串标识 OLE DB 提供程序并将提供程序指向数据源。提供程序是一个组件,用来描述数据源并以行集合的形式将信息展示给应用程序。
下表列出了几种通用数据源的 OLE DB 连接字符串:
| 数据源 | OLE DB 连接字符串 |
| Microsoft Access | Provider=Microsoft.Jet.OLEDB.4.0;Source=指向 .mdb 文件的物理路径 |
| Microsoft SQL Server | Provider=SQLOLEDB.1;Source=指向服务器上数据库的路径 |
| Oracle | Provider=MSDAORA.1;Source=指向服务器上数据库的路径 |
| Microsoft Indexing Service | Provider=MSIDXS.1;Source=指向文件的路径 |
为了向后兼容性,ODBC 的 OLE DB 提供程序支持 ODBC 连接字符串语法。下表列出了常用的 ODBC 连接字符串:
| 数据源驱动程序 | ODBC 连接字符串 |
| Microsoft Access | Driver={Microsoft Access Driver (*.mdb)};DBQ=指向 .mdb 文件的物理路径 |
| SQL Serverr | Driver={SQL Server};SERVER=指向服务器的路径 |
| Oracle | Driver={Microsoft ODBC for Oracle};SERVER=指向服务器的路径 |
| Microsoft Excel | Driver={Microsoft Excel Driver (*.xls)};DBQ=指向 .xls 文件的物理路径; DriverID =278 |
| Microsoft Excel 97 | Driver={Microsoft Excel Driver (*.xls)};DBQ=指向 .xls 文件的物理路径;DriverID=790 |
| Paradox | Driver={Microsoft Paradox Driver (*.db)};DBQ=指向 .db 文件的物理路径; DriverID=26 |
| 文本 | Driver={Microsoft Text Driver (*.txt;*.csv)}; DefaultDir=指向 .txt 文件的物理路径 |
| Microsoft Visual FoxPro®(带有一个数据库容器) | Driver={Microsoft Visual FoxPro Driver};SourceType=DBC;SourceDb=指向 .dbc 文件的物理路径 |
| Microsoft Visual FoxPro(不带数据库容器) | Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDb=指向 .dbf 文件的物理路径 |
注意 连接字符串如果使用 UNC 路径引用位于远程计算机上的数据源,可能会造成潜在的安全性问题。为了防止对您的数据源进行未经授权的访问,可以为需要访问数据的计算机创建一个 Windows 帐户,然后对数据源应用适当的 NTFS 权限。详细信息,请参阅使用 NTFS 保护文件安全。
由于性能和可靠性的原因,我们强烈推荐,使用客户端服务器数据库引擎部署数据驱动的 Web 应用程序,此程序需要能够满足约 10 个以上用户同时访问的高访问需求。虽然 ADO 适用于与 OLE DB 兼容的任何数据源,但经过广泛的测试,它主要用来与客户端服务器数据库(如 Microsoft SQL Server 或 Oracle)协同工作。
ASP 支持共享文件数据库(Microsoft Access 或 Microsoft FoxPro)作为有效的数据源。虽然在 ASP 文档中有些示例使用了“共享文件”数据库,但我们还是建议这些类型的数据库引擎只用于开发目的或有限的开发方案中。共享文件数据库可能不如客户端服务器数据库适用于高要求和高质量的 Web 应用程序。
如果正在开发 ASP 数据库应用程序,并且此程序将连接到远程 SQL Server 数据库,您还应该注意下列几点:
注意 为了在连接到远程数据库时提高性能,请使用 TCP/IP 套接字。
有关这些问题的详细信息,请访问 Microsoft 产品支持服务网站。
ADO 提供了 Connection 对象,用于建立和管理应用程序与 OLE DB 兼容数据源或 ODBC 兼容数据库之间的连接。Connection 对象的属性和方法可以用来打开和关闭数据库连接,并发布对更新信息的查询。
要建立数据库连接,首先必须创建 Connection 对象实例。例如,下列脚本创建 Connection 对象实例,接着打开一个连接:
<%
创建 connection 对象。
Set cnn = Server.CreateObject("ADODB.Connection")
'使用 OLE DB 连接字符串打开连接。
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\MarketData\ProjectedSales.mdb"
%>
注意 连接字符串在等号 (=) 的左右并不包含空格。
在上例中,Connection 对象的 Open 方法将引用连接字符串。
使用 Connection 对象的 Execute 方法,可以向数据源发出命令,如结构化查询语言 (SQL) 查询。(SQL 是与数据库进行通信的工业标准语言,定义了用来检索和更新信息的命令。)Execute 方法可以接收参数,用来指定命令(或查询)、受影响的数据记录数和所使用的命令类型。
下列脚本使用 Execute 方法,以 SQL INSERT 命令的形式发出查询,此命令用来将数据插入指定的数据库表中。在下例中,脚本块将姓名 Jose Lugo 插入 Customers 数据库表中。
<%
'定义 OLE DB 连接字符串。
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Employees.mdb"
'例示 Connection 对象并打开数据库连接。
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
'定义 SQL SELECT 语句。
strSQL = "INSERT INTO Customers (FirstName, LastName) VALUES ('Jose','Lugo')"
'使用 Execute 方法将 SQL 查询发布到数据库。
cnn.Execute strSQL,,adCmdText + adExecuteNoRecords
%>
注意,在用来执行查询的语句中指定了两个参数:adCmdText 和 adExecuteNoRecords。可选参数 adCmdText 指定命令类型,指出提供程序对此查询语句(这里是 SQL 查询语句)求值所得的应该是命令的文本定义。adExecuteNoRecords 参数指示 ADO,在没有结果返回应用程序时,不要创建数据记录集。此参数只用于定义为文本定义的命令类型(如 SQL 查询),或已存储的数据库过程。虽然 adCmdText 和 adExecuteNoRecords 是可选参数,但使用 Execute 方法时应指定这两个参数,以改善数据应用程序的性能。
要点 ADO 参数(如 adCmdText)需要在脚本中先定义然后再使用。一种方便的定义参数的方法是使用“组件类型库”,它是包含所有 ADO 参数定义的文件。要实施组件类型库,首先应声明它。将下列 <METADATA> 标记添加到自己的 .asp 文件或 Global.asa 文件中以声明 ADO 类型库:
<!--METADATA NAME="Microsoft ActiveX Data Objects 2.5 Library" TYPE="TypeLib" UUID="{00000205-0000-0010-8000-00AA006D2EA4}"-->
有关实施组件类型库的详细信息,请参阅使用变量和常量主题中的使用常量一节。
除了 SQL INSERT 命令外,还可以使用 SQL UPDATE 和 DELETE 命令更改和删除数据库信息。
使用 SQL UPDATE 命令,可以更改数据库表中各个项目的值。下列脚本使用 UPDATE 命令,将 Customers 表中所有在 LastName 字段中包含姓氏 Smith 的 FirstName 字段更改为 Jeff。
<%
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Employees.mdb"
cnn.Execute "UPDATE Customers SET FirstName = 'Jeff' WHERE LastName = 'Smith' ",,adCmdText + adExecuteNoRecords
%>
要删除数据库表中特定的记录,可使用 SQL DELETE 命令。下列脚本将删除 Customers 表中所有姓为 Smith 的行:
<%
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Employees.mdb"
cnn.Execute "DELETE FROM Customers WHERE LastName = 'Smith'",,adCmdText + adExecuteNoRecords
%>
注意 使用 SQL DELETE 命令时务必小心谨慎。不带 WHERE 子句的 DELETE 命令将删除表中的所有行。确保包括 SQL WHERE 子句,以便明确指定要删除的行。
为了检索数据、检查结果和更改数据库,ADO 提供了 Recordset 对象。正如名字所示,Recordset 对象可以用来检索和显示数据库行(或“记录”),这取决于您的查询约束条件。Recordset 对象保留由查询返回的每一条记录的位置,这样就能使您查看所有的结果,每次一条。
成功的 Web 数据应用程序既使用 Connection 对象建立链接,又使用 Recordset 对象处理返回的数据。通过综合使用这两种对象的一些特殊功能,开发出的数据库应用程序几乎可以执行所有的数据处理任务。例如,下列服务器端脚本使用 Recordset 对象执行 SQL 的 SELECT 命令。此 SELECT 命令基于查询约束条件检索信息集。此查询还包含 SQL WHERE 子句,用来将查询限制到一个指定的标准。在此例中,WHERE 子句将查询限制在 Customers 数据库表中“姓”字段包含 Smith 的所有记录。
<%
'与数据源建立连接。
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Employees.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
'例示 Recordset 对象。
Set rstCustomers = Server.CreateObject("ADODB.Recordset")
'使用 Open 方法打开记录集,
'并使用通过 Connection 对象建立的连接。
strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Smith' "
rstCustomers.Open strSQL, cnn
'遍历记录集,显示结果,
'并使用 MoveNext 方法递增记录位置。
Set objFirstName = rstCustomers("FirstName")
Set objLastName = rstCustomers("LastName")
Do Until rstCustomers.EOF
Response.Write objFirstName & " " & objLastName & "<BR>"
rstCustomers.MoveNext
Loop
%>
注意,在上例中,Connection 对象建立数据库连接,而 Recordset 对象使用同一连接从数据库中检索结果。当需要精确配置建立数据库链接的方式时,此方法非常有用。例如,如果要指定在连接中止之前的时间延迟,可能需要使用 Connection 对象设置此属性。但是,如果只想使用 ADO 的默认连接属性建立连接,您可以使用 Recordset 对象的 Open 方法来建立链接:
<%
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Employees.mdb"
strSQL = "SELECT FirstName, LastName FROM Customers WHERE LastName = 'Smith' "
Set rstCustomers = Server.CreateObject("ADODB.Recordset")
'使用 Open 方法打开连接
'并使用通过 Connection 对象建立的连接。
rstCustomers.Open strSQL, strConnectionString
'遍历记录集,显示结果,
'并使用 MoveNext 方法递增记录位置。
Set objFirstName = rstCustomers("FirstName")
Set objLastName = rstCustomers("LastName")
Do Until rstCustomers.EOF
Response.Write objFirstName & " " & objLastName & "<BR>"
rstCustomers.MoveNext
Loop
%>
使用 Recordset 对象的 Open 方法建立连接时,也隐含地使用了 Connection 对象保护链接的安全。详细信息,请参阅 Microsoft Universal Data Access 网站上的 Microsoft ActiveX 数据对象 (ADO) 文档。
注意 要明显提高 ASP 数据库应用程序的性能,可以考虑以“应用程序”状态缓存记录集。详细信息,请参阅缓存数据。
统计记录集中返回的记录数有时候很有用。Recordset 对象的 Open 方法使您能够指定可选的游标参数,以定义基础提供程序检索和浏览记录集的方法。通过向执行查询的语句中添加 adOpenKeyset 游标参数,可以使客户端应用程序完全浏览记录集。因此,应用程序可使用 RecordCount 属性精确地统计记录集中的记录数。请参阅下例:
<%
Set rs = Server.CreateObject("ADODB.Recordset")
rs.Open "SELECT * FROM NewOrders", "Provider=Microsoft.Jet.OLEDB.3.51;Data Source='C:\CustomerOrders\Orders.mdb'", adOpenKeyset, adLockOptimistic, adCmdText
'使用 Recordset 对象的 RecordCount 属性进行统计。
If rs.RecordCount >= 5 then
Response.Write "我们已收到下列 " & rs.RecordCount & " 个新订单<BR>"
Do Until rs.EOF
Response.Write rs("CustomerFirstName") & " " & rs("CustomerLastName") & "<BR>"
Response.Write rs("AccountNumber") & "<BR>"
Response.Write rs("Quantity") & "<BR>"
Response.Write rs("DeliveryDate") & "<BR><BR>"
rs.MoveNext
Loop
Else
Response.Write "新订单数少于 " & rs.RecordCount & "。"
End If
rs.Close
%>
使用 ADO Command 对象执行查询的方式与使用 Connection 和 Recordset 对象执行查询的方式一样,但是使用 Command 对象可以准备(或编译)对数据库源的查询,然后使用各种不同的值重复发出此查询。用这种方法编译查询的好处在于,当您需要重新发出修改过的已有查询时,可以大大地减少发出时间。另外,还可以留下 SQL 的部分查询不进行定义,而在执行查询之前对这部分进行更改。
Command 对象的 Parameters 集合可以使您避免每次重新发布查询时都要重建查询的麻烦。例如,如果您需要定期更新基于网站的库存系统的供应和费用信息,就可以按照下列方式预定义查询:
<%
'使用 Connection 对象打开连接。注意,Command 对象
'没有可以用来建立连接的 Open 方法。
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Inventory.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
'例示 Command 对象;使用 ActiveConnection 属性
'向 Command 对象附加连接。
Set cmn= Server.CreateObject("ADODB.Command")
Set cmn.ActiveConnection = cnn
'定义 SQL 查询。
cmn.CommandText = "INSERT INTO Inventory (Material, Quantity) VALUES (?, ?)"
'首次执行 Command 对象之后,保存 CommandText 属性中
'指定的查询的预备(或预编译)版本。
cmn.Prepared = True
'定义查询参数配置信息。
cmn.Parameters.Append cmn.CreateParameter("material_type",adVarChar, ,255 )
cmn.Parameters.Append cmn.CreateParameter("quantity",adVarChar, ,255 )
'定义并执行第一个插入操作。
cmn("material_type") = "日光灯"
cmn("quantity") = "40"
cmn.Execute ,,adCmdText + adExecuteNoRecords
'定义并执行第二个插入操作。
cmn("material_type") = "保险丝"
cmn("quantity") = "600"
cmn.Execute ,,adCmdText + adExecuteNoRecords
.
.
.
%>
要点 ADO 参数(如 adCmdText)是一些简单变量,这意味着在数据访问脚本中使用 ADO 参数之前需要先定义参数值。由于 ADO 使用了大量的参数,因此根据“组件类型库”定义参数更容易些。组件类型库是包含所有 ADO 参数和常量定义的文件。有关实施 ADO 类型库的详细信息,请参阅使用变量和常量主题中的使用常量一节。
在上例中,您将注意到脚本使用不同的值重复构建和重新发布 SQL 查询,但并没有重新定义查询以及向数据库源中重新发出查询。使用 Command 命令编译查询还有如下优点:可避免在将字符串和变量连接成 SQL 查询时出现问题。特别是使用 Command 对象的 Parameter 集合,可以避免那些与定义特定类型字符串、日期和时间变量相关的问题。例如,包含单引号 (') 的 SQL 查询值可能导致查询失败:
strSQL = "INSERT INTO Customers (FirstName, LastName) VALUES ('Robert','O'Hara')"
注意,姓 O'Hara 包含一个单引号,这与用来表示 SQL VALUES 关键字中数据的单引号冲突。通过将查询值绑定为 Command 对象参数,可以避免此类问题。
包含 HTML 表单的网页可允许用户远程查询数据库并检索指定的信息。使用 ADO,可以创建出非常简单的脚本来收集用户表单信息、创建自定义的数据库查询并向用户返回信息。使用 ASP 的 Request 对象,可以检索输入到 HTML 表单中的信息,并将这些信息嵌入到 SQL 语句中。例如,下列脚本块将由 HTML 表单提供的信息插入表中。此脚本使用 Request 对象的 Form 集合收集用户信息。
<%
'使用 Connection 对象打开连接。Command 对象没有
'可以用来建立连接的 Open 方法。
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\CompanyCatalog\Seeds.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
'例示 Command 对象,
'并使用 ActiveConnection 属性
'向 Command 对象附加连接。
Set cmn= Server.CreateObject("ADODB.Command")
Set cmn.ActiveConnection = cnn
'定义 SQL 查询。
cmn.CommandText = "INSERT INTO MySeedsTable (Type) VALUES (?)"
'定义查询参数配置信息。
cmn.Parameters.Append cmn.CreateParameter("type",adVarChar, ,255)
'指派输入值并执行更新操作。
cmn("type") = Request.Form("SeedType")
cmn.Execute ,,adCmdText + adExecuteNoRecords
%>
有关表单和使用 ASP Request 对象的详细信息,请参阅处理用户输入。
要设计一个完善的 Web 数据库应用程序(例如,为成千上万个客户服务的联机订购输入应用程序),所面临的一个主要挑战就是如何正确管理数据库连接。打开并维护数据库连接时,即使没有信息传输时,也会严重消耗数据库服务器的资源并导致连接性问题。设计完善的 Web 数据库应用程序,可重复利用数据库连接并补偿因网络通信导致的延迟。
数据库服务器当活动突然激增时会形成积压,从而大大增加了建立数据库连接所需的时间。因此,过多的连接延迟会降低数据库应用程序的性能。
使用 Connection 对象的 ConnectionTimeout,可以限制应用程序在放弃连接尝试并发出错误消息之前等待的时间。例如,下列脚本将 ConnectionTimeout 属性设置为在取消连接尝试之前等待 20 秒。
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.ConnectionTimeout = 20
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Inventory.mdb"
ConnectionTimeout 属性默认为 30 秒。
注意 在将 ConnectionTimeout 属性并入数据库应用程序之前,请确保您的连接提供程序和数据源支持此属性。
连接池可使您的 Web 应用程序使用“池”中的连接,“池”指的是包含许多不需要重新建立的自由连接的容器。创建连接并放入连接池中后,应用程序可以重复使用此连接而不必执行连接进程。这可明显地提高性能,特别是在应用程序通过网络连接或需要重复连接和断开的情况下更是如此。另外,共用的连接可被多个应用程序重复使用。
OLE DB 具有“共用”特性,称为“会话池”,用来提高大型 Web 数据库应用程序的活动性能。会话池保护连接安全和一些其他属性。共用连接仅在连接两端提出匹配的请求时才可重新使用。默认情况下,Microsoft SQL Server 和 Oracle 的 OLE DB 提供程序支持会话池。这意味着并不需要对应用程序、服务器或数据库进行配置,即可使用会话池。然而,如果默认情况下提供程序不支持会话池,则需要创建注册表设置以启用会话池。有关会话池的详细信息,请参阅 OLE DB 2.0 Software Development Kit (SDK) 文档。
如果希望 ODBC 驱动程序分享连接池,必须配置特定的数据库驱动程序,然后在 Windows 注册表中设置驱动程序的 CPTimeout 属性。CPTimeout 属性确定连接在连接池中的保留长度。如果连接在池中的保留时间超过了 CPTimeout 设置的持续时间,连接将关闭并从池中删除。CPTimeout 的默认值是 60 秒。
通过创建带有下列设置的注册表项,可以有选择性地设置 CPTimeout 属性,启用特定 ODBC 数据库驱动程序的连接池:
\HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\driver-name\CPTimeout = timeout (REG_SZ, units are in seconds)
例如,下列键值将 SQL Server 驱动程序的连接池超时设置为 180 秒(3 分钟)。
\HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\SQL Server\CPTimeout = 180
注意 默认情况下,Web 服务器激活 SQL Server 的连接池,并将 CPTimeout 设置为 60 秒。
虽然可以通过将连接储存在 ASP 的 Application 对象中,重复使用跨多页的连接,但这样做可能导致不必要地保持打开的连接,这样就无法体现使用连接池的优势。如果有许多用户需要连接到同一个 ASP 应用程序,一种更好的方法是将字符串放置到 ASP 的 Application 对象中,重复使用跨多个网页的数据库连接字符串。例如,您可以在 Global.asa 文件的 Application_OnStart 事件过程中指定连接字符串,如下列脚本所示:
Application("ConnectionString") = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Inventory.mdb"
然后在访问数据库的每个 ASP 文件中,写入下列脚本创建此页的连接对象实例:
<OBJECT RUNAT=SERVER ID=cnn PROGID="ADODB.Connection"></OBJECT>
并使用下列脚本打开此连接:
cnn.Open Application("ConnectionString")
要关闭连接,可在此页的最后写入下列脚本:
cnn.Close
在个别用户需要重复使用跨多个网页连接的情况下,您将发现使用 Session 对象储存连接字符串比使用 Application 对象更具优势。
要充分利用连接池,请尽可能显式关闭数据库连接。默认情况下,连接在脚本执行完后终止。然而,通过显式关闭脚本中不再需要的连接,可以减少对数据库服务器的需求,并使得其他用户可以使用此连接。
可以使用 Connection 对象的 Close 方法显式终止 Connection 对象和数据库之间的连接。下列脚本将打开和关闭连接:
<%
strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Inventory.mdb"
Set cnn = Server.CreateObject("ADODB.Connection")
cnn.Open strConnectionString
cnn.Close
%>