关于 OLE DB 和 .NET 的思考

关于 OLE DB 和 .NET 的思考

你我并不相识。不过,面对一个实实在在的问题“软件到底是什么?”,我却没有合适的答案。

设想一下这样一个场景:在一个旅游纪念品商店,你正专注于购买一些没用的东西(主要是纪念品),以便让到机场接你的朋友和亲戚感到开心。这时,往往会有人问你:“第一次来吗?出差还是度假?”

所以,如果你是在做和软件有关的事,而不是在度假,那你就不得不面对这个现实的问题。

那么,软件到底是什么?

回答这种关于存在的问题是很困难的,尤其是如果此时你正在闲逛,背着一背包明信片、考拉图片和袋鼠玩具,包上还印着防鳄鱼的黄色警告标志。

我努力使自己的思维自由而又尽量简单。首先,软件是跟计算机相关的。软件也和演变有关。当然,软件还与数据(特别是数据存储和操作)有关。

回到旅馆后,我仍在思考下面的问题——关于数据的存储和使用,我近年来观察到了怎样的演变?于是,我开始思考 OLE DB 及其在 .NET 方面的演变。
软件进化论
从历史角度来说,ODBC 进行了第一次严肃尝试:它试图创建一种统一的应用程序访问数据库的途径。像软件中的其他东西一样,ODBC 的设计目的是满足某种特定的需要。在信息技术永无止境的进化进程中,它开创了一个新阶段。

ODBC 必须提供一个公用的(最好是抽象的)API,用来访问数据库,而不用考虑数据库的内部细节、语言和表的组织。但是,随着时间的推移,人们发现,面对新的数据驱动应用程序的设计与构造方法,ODBC 越来越无法成功地满足需要。

软件也有自己的进化论。ODBC 以不同的名称、不同的编程模型和新的功能适应了变化,生存了下来,同时又保持了它的真正使命。ODBC 继续以 OLE DB 的名称和功能提供(或多或少地)开放式数据库连接的功能。

OLE DB 作为一种编程接口,将 Microsoft 通用数据访问 (UDA) 策略的理论概念应用于实践。UDA 能够通过基于 COM 的单一编程接口来访问各种类型的数据,包括关系型、非关系型和层次结构型数据。

OLE DB 是作为一种组件技术而设计的,其特点是采用了多层模型。在 COM 桥的一侧是用于保留数据的服务器组件,另一侧则是了解如何连接和请求数据的客户端组件。前者称作 OLE DB 数据提供者;而后者则称作 OLE DB 使用者。

使用者和提供者都是 COM 对象,并能够通过一套 COM 接口互相通信。这种基于 COM 的通信可被概括为在抽象对象(如 DataSource、Session、Command 和 Rowset)上执行的操作。因此,当使用者连接到 DataSource,打开 Session,发出 Command,并返回数据 Rowset 时,便会出现这种情况。

ODBC 的这一进化使 UDA 和 OLE DB 添加了一种功能,这种功能就像一个简单的关系表一样,将所有的企业数据粘合在一起,不论它们是关系型、非关系型还是层次结构型。
OLE DB 模型
说到数据访问,我们有两种基本选择。一种是像 UDA 允许的那样,采用通用数据访问策略。另一种则倾向于使用通用数据结构。它强行将现有的所有信息从当前的数据存储区移动到一个能包容所有数据类型的数据库服务器。

使用 OLE DB,需要将客户所有的信息粘合在一起。另一种方式是,强行将客户端升级至新的、更强大的、唯一的 DBMS,而这个 DBMS 能够处理任何格式的信息。

与 ODBC 相比,OLE DB 对数据物理结构的依赖更少。此外,它不必严格基于 SQL。OLE DB 命令可以是 SQL 语句,也可以是其他的一些东西。总的说来,可以将它们看作以任何能够为目标提供者理解的语法写成的文本字符串。

像 ODBC 一样, OLE DB 采用 C++ 的概念进行设计,以尽可能提高中间层模块数据访问的性能。基于同样的原因,OLE DB 不能直接在 Visual Basic 或 ASP 中使用。

而不计其数的分布式系统却是使用 Visual Basic 来生成组件的。这就是 Microsoft 引入 ActiveX 数据对象 (ADO) 库的主要原因。

ADO 的编程接口比原始的 OLE DB SDK 更加丰富。虽然在 C++ 应用程序中使用 ADO 是完全可行的,但是 OLE DB 调用经过的代码层次较少,与相应的 ADO 代码相比,能更直接地到达数据。

虽然 ADO 很明显是在 OLE DB 上生成的,但是调用原始 OLE DB 接口和通过 ADO 运行时发出的调用具有不同的相对速度。这一事实导致了语言之间的差异。哪一种更好、更值得推荐呢?是 OLE DB 的 C++ 高性能层次还是 Visual Basic 组件中更简单、更友好的 ADO 模型?

除了提供者和使用者,OLE DB 模型还包括第三个元素——OLE DB 服务。服务是一种 COM 组件,用于处理返回给使用者的“行集”。它就像挂钩一样工作,监督使用者和提供者之间的所有通信。ADO 在很大程度上依赖 OLE DB 服务来添加其扩展功能,如数据塑型、持久性和断开的记录集。

因此,自从人们开始重视构建基于 COM 的分布式应用程序以来,就开发了各种针对某些特定领域的最佳实例。为改进 Web 应用程序的可伸缩性,人们转而使用数据访问断开模型。

简单说来,数据使用者和数据提供者并不总是连接的。一旦建立了连接,便可以发出指定的查询,获取记录并将其放至内存中的存储库,然后从数据源断开连接。然后您再在脱机状态下处理这些记录,并在需要时重新连接或提交更改。这一模型不是在所有情况下都可以使用,不过,一旦它发生作用,您就会发现它在可伸缩性和总体性能方面非常有价值。

许多系统已经进行了转换(或再转换),通过客户端游标服务来部署 ADO 记录集,从而启用数据断开。OLE DB 还不是专用于此类交互的模型,所以 ADO 是通过中间 OLE DB 服务进行扩展的。

由于其结构所固有的灵活性,OLE DB 可以成功地应用于断开连接方案,但是,这当然不代表最佳的工作方式。这一实现方案的另一小小的限制是:方案较多地依赖 ADO 记录集进行工作,以至于人们怀疑它不可能总是把每件事都做好。这样的对象如何才能在各种情况下成为最快的工作工具,不论是连接还是断开,有没有 XML,是创建的还是从磁盘加载的?

此外,考虑到 ADO 的功能包与原始 OLE DB SDK 显著不同,使用 OLE DB 将导致明显的不一致现象。

因此,ADO.NET 成为数据访问技术进化中的下一步骤。不过,从名称上看来,ADO.NET 似乎只是 ADO 的继承者。.NET 中的 OLE DB 又是怎样的?
.NET 托管提供者
永恒的进化论规律现在将 OLE DB 技术向前推进了一步,以满足新用户的要求。在 .NET 中,Web 应用程序首先是一个断开的应用程序,它利用新设计的特殊工具来管理数据。

.NET 框架使得类能够处理数据。这些类——特别是 ADO.NET 和 XML 名称空间——可供收集、读取和写入。ADO.NET 和 XML 子系统最终取代了 ADO 和 OLE DB SDK。现在,您拥有了一个唯一的、以语言为中心的方法来获取和设置数据。

ADO.NET 类对数据源的抽象能力甚至比 ADO 还要好,因为它明确设计为以数据为中心,而 ADO 中仍然使用以数据库为中心的设计。

.NET 中对应于 OLE DB 数据提供者的部分称为“托管提供者”。它们的作用如下图所示。

图 1:托管提供者层次结构图

在 OLE DB 中可以按照相似性来识别两个交互的层,即我上面提到的托管使用者层和托管提供者层。在处理数据时,.NET 应用程序不必将特殊的类或组件作为使用者模块使用。

如果 .NET 应用程序只使用本机框架中的 DataSet 或 DataReader 对象,则其将立即成为“托管”数据使用者。要真正地获取数据,应使用从 DataSetCommand 和 DBCommand 中继承的特殊类的实例。这些类代表了到数据源的链接。

你只需使用了解如何处理给定提供者的导出类,而不用指导通用对象来处理给定的提供者。所以出现的情况是,SQLDataSetCommand 将处理 SQL Server 数据库,而 ADODataSetCommand 将包装所有现有 OLE DB 提供者。

托管提供者将隐藏在这样的 DataSetCommand 类中。你永远不会意识到它们的存在,也无需特意了解它们。只要使用类和设置属性就可以了,这让人感到愉快。

在这种情况下,上图中的托管提供者层使用的交互模块与 OLE DB 甚至更早的 ODBC 中使用的模块没有太大不同。使用者命令类针对的是包装数据源的特定组件。它了解用于在源中读写数据行的协议。它还以一种 .NET 类能够很好处理的格式返回结果。

为便于理解,让我们回顾一下 OLE DB 和 .NET 数据检索的共性。

OLE DB 提供者.NET 托管提供者标识COM progID包装在命令类中返回结果Rowset 或 ADO RecordsetDataSet 或 DataReader 类更新方式提供者的特殊命令提供者的特殊命令传送格式二进制XML

表 1:比较 OLE DB 和 .NET 数据提供者

目标提供者是通过其位于 OLE DB 中的 COM progID 来识别的,而在 .NET 中,这些细节隐藏在访问器类中。

OLE DB 提供者总是返回行集——COM 对象主要提供 IRowset 接口。如果通过 ADO 访问数据,行集会转换为更丰富和更脚本化的对象,称作记录集。

.NET 应用程序只使用具有不同功能的各种类。DataReader 类是一个简单、快捷、只能前进的游标,在连接状态下工作并按记录来提供访问。结束后必须显式断开连接。相反,DataSet 对象是内存中的断开连接集合表。它是 DataSetCommand 类的填充的实例。DataSet 对象的内容建立在 DataSetCommand 从数据源取回的 XML 流的基础上。

我将在以后的专栏中讲述有关 DataReader 和 DataSet 的内容。

数据以二进制格式从提供者到达使用者,如果部署了 OLE DB,则还会经过 COM 配置。而在 .NET 中,托管提供者将返回一个 XML 流。

两种提供者都支持查询语言(通常是 SQL 和各个供应商特有的扩展)。通过该语言可以执行更新和询问数据源。

那么,OLE DB 数据提供者和 .NET 数据提供者之间的区别是什么呢?抽象地说,它们使用相同的数据访问策略。但是托管提供者更加简单和专业。两个主要的原因导致了其性能的优越性。首先,托管提供者不使用 COM 互操作桥来获取和设置数据。作为 COM 组件,OLE DB 提供者在这一点上别无选择。其次,托管提供者通常利用来自供应商的内部数据源知识来更快地获取和设置行。OLE DB 提供者也是这样做的,但是当在 .NET 内部使用时,OLE DB 提供者必须为其基于 COM 的特性付出代价,并且需要额外的代码将数据转换为 .NET 特有的类。
现有的托管提供者
像在 Beta 1 中一样,NET 框架的特色是具有两个托管提供者:一个用于 SQL Server(7.0 版本或更高),一个用于所有能够通过 OLE DB 提供者获得的数据源。

SQL Server 托管提供者隐藏在特定的类(如 SQL DataReader、SQL DataSetCommand 和 SQLCommand)后。这些类直接访问低层的 SQL Server 文件系统。下图是提供者的类图。该图将以前的通用架构映射至 SQL Server 托管提供者。

图 2:SQL Server 托管提供者的类图

OLE DB 托管提供者在 .NET 中的作用与 ODBC OLE DB 提供者在 Windows DNA 系统中的作用是相同的。简单说,它体现了后向兼容性,也反映了这样一个事实,即所有 .NET 应用程序均可以面向任何以 OLE DB 为基础的现有数据源。OLE DB 托管提供者的类图如下所示。

图 3:OLE DB 托管提供者的类图

请注意在 Beta 2 中,ADOxxx 类需要重命名为 OleDbxxx。

OLE DB 托管提供者将 .NET 类提供给调用方,但利用指定的 OLE DB 提供者来获取行。.NET 应用程序与底层 OLE DB 提供者(COM 对象)之间的通信通过 COM 互操作桥发生。

总的来说,在 .NET 中通过上述两个提供者均可以访问 SQL Server 7.0(及更高版本)的表。SQL Server 的托管提供者直接从 DBMS 文件系统请求数据,而 OLE DB 托管提供者依赖 SQLOLEDB OLE DB 提供者的服务,从而导致需要经过额外层次的代码。

现在,如果你面对的是 SQL Server 以外的任何数据源,那么 OLE DB 托管提供者是唯一的通道。通过同一通道,你还可以到达任何 ODBC 数据源。

OLE DB 托管提供者是在 COM 互操作桥上生成的瘦包装,可以调入本地 OLE DB 提供者。除了设置和终止调用,这一模块还负责将返回的行集包装至 DataSet 或 ADO DataReader 对象,以便进行后续 .NET 处理。

在 .NET 代码层,通过本地托管提供者或 OLE DB 提供者访问 SQL Server 表实际是对涉及到的类的前缀进行更改。以下是用于 SQL Server 的代码:

Dim strConn, strCmd As StringstrConn = "DATABASE=Northwind;SERVER=localhost;UID=sa;PWD=;"strCmd = "SELECT * FROM Employees"Dim oCMD As New SQLDataSetCommand(strCmd, strConn)Dim oDS As New DataSetoCMD.FillDataSet(oDS, "EmployeesList")

以下是用于 OLE DB 提供者的代码(不同之处以粗体表示):

Dim strConn, strCmd As StringstrConn = "Provider=SQLOLEDB;" strConn += "DATABASE=Northwind;SERVER=localhost;UID=sa;PWD=;"strCmd = "SELECT * FROM Employees"Dim oCMD As New ADODataSetCommand(strCmd, strConn)Dim oDS As New DataSetoCMD.FillDataSet(oDS, "EmployeesList")

由此可见,表面上的不同是非常小的;只有连接字符串和命令类不同。而使用一种类还是另一种类,差别却是非常大的。
OLE DB 的存在性问题
.NET 托管提供者代表了数据访问技术演化的下一步发展方向,但是,在 Beta 1 中还没有文档化的 SDK 涉及数据源特定的托管提供者。几个关于 OLE DB 和 .NET 的基本问题是无法忽略的。它们正在等待着 Beta 2。

难道为 OLE DB 开发的所有代码只是过时的代码吗?公司已经投入(而且经常是仍然在投入)的为自己的数据编写提供者的一切努力将会如何?

坚守你的信念——OLE DB 不是一项消亡的技术。尤其是对于功能丰富、通用并且独立于 .NET 的编程接口,它仍然是基本的规范。它不专门针对 .NET,但它获得了很好的支持。

这就是说,如果要公开自定义数据,就不能忽略 .NET 和托管提供者的出现。那么,什么是包装数据提供者的最佳接口呢?你应该怎样计划尽快公开你的数据呢?例如,从下个星期一上午 8 点开始?

.NET 使用开放的标准并广泛地基于 XML。在这种情况下,如果你需要公开拥有所有权而又基于文本的数据,则只需要考虑使用 XML(可能是自定义方案)来发布。在 .NET 中有这么多的工具可与 XML 数据配合工作,包装类的生成应该完全没有问题。

对于更复杂的数据存储,OLE DB 提供者仍是有意义的,因为你的用户群更大,而且可能不仅仅局限于 .NET。对于 .NET 专有的应用程序,托管提供者当然可以提供巨大的性能优势,但我对此持非常谨慎的态度——尤其是要在这样短的时间内做出决定!不要忘记,目前为止还没有发布有关托管提供者的任何 SDK,尽管 Microsoft 已经做出了这样的承诺。

总之,这个星期一早晨我将要开始编写的下一个数据提供者将会包括一对 OLE DB 数据提供者和一个使用 XML 的 .NET 包装类。我的首要选择不会是用 .NET 类通过 COM Interop 来包装 OLE DB 提供者。我宁可使用同样的、经过一定调整的源代码。在这种情况下,托管 C++ 很可能是便于重用“物理”代码的最佳语言。
OLE DB 的结局
让我们将此作为一种预言,留待从现在开始的未来几年验证。我要冒昧地说,OLE DB 将与 SGML(标准通用标记语言,XML 的前身)一样,其最终结局不会很理想。

作为数据交换世界的救世主而引进的 SGML 从来没有成为事实上的标准,也许是因为对于日常使用来说它太过强大和复杂了。事实是,它令人激动的原理经过了适当的缩减和特殊化,并生成 XML,然后才被广泛地接受。

我的预言是,一旦 .NET 稳固了其基础,OLE DB 将逐渐丧失其重要性,直至最终消失。我不能确定这一过程将会持续多长时间,但我确信这一点。

论据就在后面 <g>。不要走开。
对话:是的,现在我觉得过时了
你很可能生活在另一个时空!你该如何将现有的 ADO 代码定义为陈旧代码(在大多数情况下,这些代码是在六个月内写成的。)?以 .NET 技术/平台的名义?它甚至还没有进入 Beta 程序的第二阶段。

没有任何重点的生活是什么样子的?无论如何,这个问题问得好。

面对近来许多 DNA 系统中的 ADO 代码,我们能够将它们定义为陈旧的代码吗?我的答案仍是:“是的,我们会。”但是我确实理解,这听起来实在令人迷惑。

我认为,“陈旧代码”就是不再适合宿主平台核心的代码。相信我,这的确是 .NET“即将”面对的状况。当然,还是有方法在 .NET 中将现有代码、组件和应用程序结合起来的。

.NET 是一场非暴力革命,在未来的几年中,它将吸取 Windows 软件中的任何有生命力的实例。反抗是徒劳的——你注定会被同化。无论代码的年龄如何,在我对“陈旧”的定义中,真正重要的是源代码与运行时的一致性。

.NET 改变了 Windows 运行时,使其被托管。虽然 COM 和 Windows SDK 还没有完全丧失生命力,但你必须根据另一个模型来编写代码。不管这一新的运行时的基础是什么,一种崭新的模型将会与旧模型展开竞争。这一新模型将是未来 Windows 的模型。

Windows 不会灭亡,但是它将改变。COM 不会灭亡,但它将不得不面对 .NET 类。ADO 不会灭亡并将继续发挥作用,但是以 ADO.NET 为特点的 .NET 才是 ADO 的未来。

.NET 并不简单的就是 Windows 6.0,ADO.NET 也不是以前称作 ADO 3.0 的奇妙新名字。它是不同的,又是普遍适用的。它是新的平台。其他的内容或者是另一个平台,或者是陈旧的代码(当集成在一起时)。

陈旧代码是不论存在时间的。我知道人们还是会编写 DNA 系统,在这一周,在六个月内,甚至在 .NET 发布后。我并不是说这是完全错误或是应该绝对避免的。只是要提醒你,你正在逆潮流而动。

 

时间: 2024-11-02 20:31:23

关于 OLE DB 和 .NET 的思考的相关文章

关于OLE DB的.NET思考(转自微软)

微软 关于 OLE DB 和 .NET 的思考 你我并不相识.不过,面对一个实实在在的问题"软件到底是什么?",我却没有合适的答案.设想一下这样一个场景:在一个旅游纪念品商店,你正专注于购买一些没用的东西(主要是纪念品),以便让到机场接你的朋友和亲戚感到开心.这时,往往会有人问你:"第一次来吗?出差还是度假?"所以,如果你是在做和软件有关的事,而不是在度假,那你就不得不面对这个现实的问题.那么,软件到底是什么?回答这种关于存在的问题是很困难的,尤其是如果此时你正在闲

使用OLE DB和ADO调用返回记录集的Oracle存储过程

摘要 OLE DB是建立在ODBC成功基础上的一种开放规范,它为访问和操纵不同类型数据提供开放的标准.ADO是OLD DB的一个消费者,它提供了对OLE DB数据源应用级的访问功能.在应用程序中使用OLE DB和ADO,可以高效地调用返回记录集的Oracle存储过程. 关键字 OLE DB ADO 存储过程 记录集 1 前言 在基于Oracle数据库的ADO应用程序的开发过程中,为了提高执行速度和降低网络流量,往往要在应用程序中调用Oracle数据库服务器端的存储过程.有的存储过程需要返回多行的

通过 OLE DB 连接 MSSQL Server时出现乱码的解决方法

server|解决 当使用OLE DB方式与MS SQL Server连接时,如果数据库的代码页与本地的不同,当进行查询时字符的返回值就会变成 ? 或是乱码, 微软的网站上说这是一个BUG, 并且描述如下:When you try to retrieve character data from a column with different collation than the client code page in Microsoft SQL OLE DB Provider (SQLOLEDB

OLE DB Method for SQL

在第一部分,我们讨论了如何优化 ASP 代码.在这一部分,我们把重点放在数据访问上. 一般情况下,数据访问时间要比 ASP 代码解释,编译时间长,不要让数据检索成为影响 ASP 性能的瓶颈. 首先,讲一些老生常谈的话.比如:需要声明变量,要用 Response.Write SQL_string 来进行调试,要用 On Error Resume Next 来捕获错误.不要在 Application 和 Session 中存储 Connection 对象等等,都是一些很多人知道而又不屑一顾的常识.

odbc和ole db在连接数据库时有什么区别?

odbc|连接数据库|区别 值得注意的是,OLE DB对ODBC的兼容性,允许OLE DB访问现有的ODBC数据源.其优点很明显,由于ODBC相对OLE DB来说使用得更为普遍,因此可以获得的ODBC驱动程序相应地要比OLE DB的要多.这样不一定要得到OLE DB的驱动程序,就可以立即访问原有的数据系统.提供者位于OLE DB层,而驱动程序位于ODBC层.如果想使用一个ODBC数据源,需要使用针对ODBC的OLE DB提供者,它会接着使用相应的ODBC驱动程序.如果不需要使用ODBC数据源,那

OLE DB取得数据库的架构信息

架构|数据|数据库 关于如何取得数据库架构信息,对于取得SQL Server和Oracal的数据库结构可能比较简单,方法也比较多. 这里整理了一个对于所有能用ADO.Net链接的数据库(比如Access,db4格式的dbf自由表等)都通用的方法 1.首先就是链接各种数据库的链接字符串,都是用ADO.Net,命名空间是:using System.Data.OleDb; 用几种数据库举个例子,需要其他的数据库链接可以到这里查:http://www.connectionstrings.com/ 但要是

SQL Server.net 和 OLE DB.net连接数据库的比较

server|比较|连接数据库 ADO.net的数据库访问是他通过被称为"数据提供程序(data provider)"的软件模块进行的..net框架1.0版本是"分裂人格"的,就是他提供了两个数据提供程序:SQL Server.NET提供程序和OLE DB.NET提供程序. SQL Server.NET提供程序 它是Microsoft SQL Server数据库的接口,不需要任何非托管提供程序的帮助. OLE DB.NET提供程序 它是通过OLE DB提供程序访问数

在.NET里使用Visual FoxPro资源-Visual FoxPro OLE DB Provider

第一部分:Visual FoxPro OLE DB Provider 说起 Fox,第一个印象就是DBF 数据表格,将近20年的发展历程,不知道有多少系统使用DBF存放数据.转入 .NET 平台以后,怎样访问 Fox系列数据自然是很多开发人员关心的问题. 在 Visual FoxPro 7以前,微软只提供了Fox的ODBC的驱动程序.通过ODBC访问Fox数据效率比较低,更要命的是Visual FoxPro 3中增加的数据库容器(Database Container,简称DBC)中的许多特性都不

OLE DB provider “SQLNCLI11” for linked server “dbLink01”

OLE DB provider "SQLNCLI11" for linked server "dbLink01" was unable to begin a distributed transac 从网上搜集了以下几个解决方案,但对于非同网段的分布式事务,还是解决不了: 我这边报处错误的详细信息是: 异常信息:The operation could not be performed because OLE DB provider "SQLNCLI11&qu