Wei-Meng Lee
在数据库出现的早期,开发人员只需要了解正在使用的数据库产品的详尽知识。但数据库产品和技术发展很快。从关系数据库到非关系数据存储区(如电子邮件和文件系统),数据访问技术必须始终追随技术的飞速变化。并且,随着客户端/服务器及多层应用程序结构的出现,现在开发人员必须了解多种数据访问技术。大多数开发人员花了数年时间学会了许多缩写词所对应的技术,例如,ODBC、DAO、RDO、OLE DB、ADO 和 RDS。现在 Microsoft 已经推出 .NET 框架,并且,随之还有另外一项新的数据访问技术:ADO.NET。
当我们沉浸于每一项新的技术进步时,常常会忽略数据访问技术是如何演进的,以及每项技术应运而生的理由。了解这些技术的进展 £; 从 ODBC 到 ADO.NET £; 有助于为自己的机构选择合适的技术并对其进行优化。
ODBC
在最基本的数据库设计类型中,应用程序仅依赖一个数据库。在这样简单的设置中,应用程序开发人员可以直接针对数据库系统的接口进行编程。此方法虽然提供了一种快速而有效的数据访问方式,但当企业发展、开发人员需要扩展应用程序时,它却常常成了阻碍发展的一个大问题。单数据库的方法还意味着,每个现有的应用程序都必须有不同的版本以支持各个数据库。随着业务的变化、发展和合并,应用程序必须访问运行于不同平台的多种数据库。
ODBC 技术为访问异类的 SQL 数据库提供了一个共同的接口。ODBC 使用 SQL 作为访问数据的标准。第 30 页的图 1 显示了标准 ODBC 结构的关系图。这一接口提供了最大限度的互操作性:一个应用程序可以通过共同的一组代码访问不同的 SQL 数据库管理系统 (DBMS)。因此,开发人员可以构建并分布客户端/服务器应用程序,而无需针对特定的 DBMS。
开发人员可以添加数据库驱动程序,将应用程序与用户所选的 DBMS 联系起来。如图 1 所示,驱动程序管理器提供应用程序与数据库之间的中间链接。ODBC 接口包含一系列功能,由每个 DBMS 的驱动程序实现。当应用程序改变它的 DBMS 时,开发人员只使用新的 DBMS 驱动程序替代旧的驱动程序,并且应用程序可以照常运行 £; 无需修改代码。
DAO 和 RDO
ODBC 使用低层接口,因此 C 和 C++ 程序员是真正从 ODBC 技术受益最多的人。Visual Basic (VB) 程序员没有一种简单的方法来访问 ODBC 接口。在 VB 6.0 之前,开发人员不得不依赖一种较高级别的数据访问模式。第 30 页的图 2 显示了 VB 程序员如何用数据访问对象 (DAO) 访问数据库。
DAO 是建立在 Microsoft Jet£¨Microsoft Access 的数据库引擎)基础之上的。Jet 是第一个连接到 Access 的面向对象的接口。使用 Access 的应用程序可以用 DAO 直接访问数据库。由于 DAO 是严格按照 Access 建模的,因此,使用 DAO 是连接 Access 数据库最快速、最有效的方法。DAO 也可以连接到非 Access 数据库,例如,SQL Server 和 Oracle。DAO 使用 ODBC,但是由于 DAO 是专门设计用来与 Jet 引擎对话的,Jet 将解释 DAO 和 ODBC 之间的调用。使用除 Access 之外的数据库时,这种额外的解释步骤导致较慢的连接速度。
要克服这样的限制,Microsoft 创建了 RDO。第 30 页的图 3 显示了 RDO 如何直接访问 ODBC API,而无需通过 Jet 引擎。不久之后,Microsoft 推出了 ODBCDirect,它是 DAO 的扩展,在后台使用 RDO。第 30 页的图 4 显示 ODBCDirect 如何允许现有的 DAO 应用程序访问数据库,而没有 Jet 引擎产生的性能损失。
OLE DB
多年以来,ODBC 已成为访问客户端/服务器数据库的标准。ODBC 提供了基于标准的接口,接口要求 SQL 处理功能,并被优化用于基于 SQL 的方法。然而,如果要访问不使用 SQL 的非关系数据源(例如,不按照关系存储数据的 Microsoft Exchange Server)中的数据,情况会如何呢?
进入 OLE DB。OLE DB 建立于 ODBC 之上,并将此技术扩展为提供更高级数据访问接口的组件结构。此结构对企业中及 Internet 上的 SQL、非 SQL 和非结构化数据源提供一致的访问。(实际上,在访问基于 SQL 的数据时,OLE DB 仍使用 ODBC,因为对于 SQL 它是最优结构。)如第 32 页的图 5 所示,OLE DB 由三个组件构成:数据使用者(例如,一个应用程序);包含并公开数据的数据提供程序以及处理并传输数据的服务组件(例如,查询处理器、游标引擎)。OLE DB 是一个针对 SQL 数据源和非 SQL 数据源(例如,邮件和目录)进行操作的 API。
ADO
OLE DB 为 C 和 C++ 程序员及使用其他包含 C 样式函数调用语言的程序员提供绑定。有一些语言(例如 VB 和 VBScript)不提供指针数据类型(地址变量)。因此,这些语言不能使用 C 样式绑定,而且不能直接调用 OLE DB。
在此基础上,Microsoft 推出了另一个数据访问对象模型:ADO。ADO 采用基于 DAO 和 RDO 的对象,并提供比 DAO 和 RDO 更简单的对象模型(尽管会产生一些冗余的功能,如现在进行一项操作时可以用不止一种方法)。ADO 中的对象层次结构比 DAO 中的更平缓。ADO 包含一些简化对数据存储区数据的访问任务的内置对象。
第 32 页的图 6 显示了应用程序连接到数据库可采取的许多途径。例如,VB 程序员可以使用 ADO 将应用程序连接到 OLE DB 提供程序。如果数据库不支持 OLE DB,应用程序可以通过 ODBC 连接。Visual C++ (VC++) 程序员可以使用 ADO 或直接通过 OLE DB 连接。
ADO 中的示例
让我们看一个简单示例,它显示 ADO 是如何运行的。第 32 页的清单 1 显示可如何使用典型的记录集对象 £; ADO 中的核心对象。记录集对象表示一系列记录(很像一个表),并支持游标类型,例如,adOpenForwardOnly、adOpenKeyset、adOpenDynamic 和 adOpenStatic。游标可以在服务器端(默认情况下),也可在客户端。
要访问一条记录,ADO 需要按顺序扫描记录集。要访问多个表,需要执行 JOIN 查询,并将返回的结果作为记录集。虽然记录集对象支持断开的数据访问,ADO 还是主要为连接的数据访问而设计。这种连接的访问模式占用服务器端的重要资源。另外,要传输记录集,必须使用 COM 封送处理。COM 封送处理是数据类型转换过程,这种转换占用额外的系统资源。
从 ADO 2.1 开始,Microsoft 将 XML 支持添加到 ADO 对象模型,这样就可将记录集保存为 XML 文档。然而,直到 ADO 2.5 出现,ADO 2.1 中 XML 支持的一些限制(例如,分层记录集对象的保持)才被取消。虽然 ADO 可以将 XML 文档读入记录集,但它只能读取名为高级数据表图 (Advanced Data TableGram, ADTG) 的专用架构。
Microsoft 希望拥有断开的数据访问机制,它扩展了 ADO 并推出远程数据服务 (RDS)。RDS 是按照 ADO 建模的,无需实时连接就可以使记录集传输到客户端(例如,Web 浏览器)。然而,如同 ADO 一样,RDS 使用 COM 封送处理将记录集从服务器传输到客户端。
.NET 时代
在开始设计 .NET 框架时,Microsoft 就以此为契机重新设计了数据访问模型。Microsoft 没有进一步扩展 ADO,而是决定设计一个新的数据访问框架 £; 但保留了缩写词。Microsoft 根据其成功的 ADO 对象模型经验设计了 ADO.NET。但 ADO.NET 满足了 ADO 无法满足的三个重要需求:提供了断开的数据访问模型,这对 Web 环境至关重要;提供了与 XML 的紧密集成;还提供了与 .NET 框架的无缝集成(例如,兼容基类库类型系统)。
ADO.NET 结构。图 7 显示了 ADO.NET 的结构。但缺少了能够在 ADO 中执行诸多功能的记录集对象。ADO.NET 具有几个专用对象以执行特定任务,用于代替记录集对象。表 1 描述了其中的三个专用对象:DataAdapter、DataReader 和 Dataset。
.NET 数据提供程序。.NET 数据提供程序实现 ADO.NET 接口,是 ADO.NET 的一个基本组件。例如,一个 .NET 数据提供程序会实现 DataReader 对象,以便应用程序和数据集对象能够使用它。
一个数据提供程序包含四个主要对象:Connection 对象,用于连接数据源;Command 对象,对数据源执行命令;DataReader 对象,在只读和只进的连接模式下从数据源读取数据;DataAdapter 对象,从数据源读取数据并使用所读取的数据填充数据集对象。
Visual Studio .NET 包括两个 .NET 数据提供程序。SQL Server .NET 数据提供程序用于连接 SQL Server 7.0 和更高版本数据库。如果使用 SQL Server 7.0 和更高版本,这种访问方法是非常有效的,因为 SQL Server .NET 数据提供程序通过表格数据流 (TDS) 协议直接和 SQL Server 通讯。OLE DB .NET 数据提供程序用于连接非 SQL Server 数据库,如 Oracle 或 IBM DB2。该数据提供程序针对相应的数据库使用 OLE DB 提供程序。
在本文写作之时,Microsoft 刚刚发布了用于 .NET 的第三个数据提供程序 - ODBC .NET 数据提供程序 - 的 Release Candidate Beta 版本。您可以从位于 http://www.microsoft .com/data/download_odbcnetrc.htm 的 Microsoft 站点下载该数据提供程序。
图 8显示了应用程序通过 ADO.NET 连接数据库可采用的各种途径。在选择途径时,首先要考虑的因素是应该使用何种 .NET 数据提供程序的问题。如果使用 SQL Server 7.0 或更高版本,选用 SQL Server .NET 数据提供程序是合理的。如果数据库是 SQL Server 6.5 或任何 OLE DB 提供程序随附的非 SQL Server 数据库(例如,Oracle),则应使用 OLE DB .NET 数据提供程序。注意,即使是使用 SQL Server 7.0 或更高版本,您仍然可以使用 OLE DB .NET 数据提供程序,但会失去通过 TDS 直接和 SQL Server 通讯时的性能优势。然而,该非特定途径的优势在于可移植性 £; 无需修改代码就可以交换所使用的数据库中的数据。
其次,确定需要执行的任务。如果只需从数据源中读取和显示数据,DataReader 对象可能就足够了。但是,如果需要操作数据(可能需要执行某些编辑和删除),则应使用数据集对象。只在需要时才使用数据集,因为数据集本身就比 DataReader 慢。(数据集使用 DataReader 来填充它的表。)
ADO.NET 中的示例
来看一看 Web 服务中 ADO.NET 的操作。清单 2 显示了返回数据集对象的 Web 服务。清单 2 中的代码和清单 1 中的代码类似。清单 2 中的 Web 服务从 Pubs 数据库检索 Authors 表并将其公开为 Web 服务。Web 服务使用 SQL Server .NET 数据提供程序,如下列命名空间导入行所示:
Imports System.Data.SqlClient
首先,Web 服务和 SQL Server 2000 数据库建立连接:
Dim conn AS New SqlConnection("server=localhost; uid=sa; password=; database=pubs")
然后,Web 服务使用 Command 对象对数据库执行一个查询:
Dim comm AS New SqlCommand(sql, conn)
接下来,Web 服务使用 DataAdapter 对象填充数据集:
DataAdapter.Fill(ds, "Authors_table")
请注意,连接会在填充数据集后立刻关闭,而不像 ADO 中的连接,在遍历记录集时必须打开。结果产生的数据集作为 Web 服务返回。图 9 显示了在执行新的 Web 服务时获取的一部分数据集。数据集及其架构以 XML 格式表示。客户端应用程序可以通过使用 DataGrid 来绑定该数据集。清单 3 显示了执行此绑定的代码。 图 10 显示了在 ASP.NET Web 应用程序中,结果产生的数据集绑定到 DataGrid 控件的情形,该图以对用户更加友好的格式显示数据集。ASP.NET 提供了很多自动绑定到数据集的服务器控件。
在 .NET 应用程序中使用ADO
虽然 ADO.NET 具有许多强大的新功能,但由于各种原因,您可能希望继续使用 ADO。(有关决定是否转换到 ADO.NET 或同时使用 ADO 和 ADO.NET 的更多信息,请参阅 Dino Esposito 的 "A Soft Landing to ADO.NET" 一文的第 37 页。)如果您正在开发新的 .NET 应用程序,应选择 ADO.NET。但如果您正在迁移应用程序,则可能希望在现有项目中保留 ADO,并使用 ADO.NET 启动新项目。.NET 框架允许通过 COM interop在 .NET 应用程序中使用 ADO,它提供向后兼容性而无需修改 ADO。您需要以程序集形式导入 ADO 类型库,如图 11 所示。然后,可使用 ADO 作为示例代码, 如清单 4 所示。
做出明智的选择
数据访问技术正在不断地发展。甚至在掌握一门技术之前,另一门技术就已经产生了。只有一件事是确定的:在应用程序开发中,数据库扮演着越来越重要的角色。了解最新的技术 £; 以及产生该技术的发展变化 £; 将有助于为当前工作选择合适的技术,并有助于在组织需要变化时做出明智的选择。