自译MSDN文献 《摆脱开发者对 CommandBuilder的依赖》

摆脱开发者对 CommandBuilder 的依赖

William Vaughn
Beta V Corporation

2003 年 3 月

对应 :
Microsoft® ADO.NET

** 摘要 ** ** : ** 分析 ADO.NET CommandBuilder 原理 , 并演示如何使用 Visual Studio .NET DataAdapter 配置向导 (DACW) 构建查询命令 . (11 页 )

目录

CommandBuilder 所支持的操作 _ _
从基于 COM 的 ADO 升级
ADO.NET CommandBuilder 如何工作 s
其他的方法 ?
创建查询动作命令
检察生成的代码
调整 UpdateCommand
调整 DeleteCommand
总结

我参加了本周微软主持的一次技术交流
( http://communities2.microsoft.com/home/chatsevents.aspx ). 我意外的与微软 .NET Framework 开发团队及其他一些勇于尝试新技术的人士进行了交流 . 这次谈话包含了其他开发者对 ** CommandBuilder ** 的研讨 . 在公众新闻组每天也能见到许多相关话题 , 因此我认为是时候将相关话题做一并解答了 .

CommandBuilder 所支持的操作

我们首先从基础开始 , 即 Microsoft® ADO.NET. ADO.NET 使用新技术更新行集 . 如果熟悉 Microsoft® Visual Basic 6.0 Data Object Wizard ( VB6 数据对象向导),这并不算全新的概念 . (Homer Simpson 如此表达 , "D'Oh!") 如同 Data Object Wizard, ADO.NET DataAdapter 用来管理四种命令对象 . 其中一种命令用来获取行集 其它三种命令分别用来增加、更新 删除行集 。

· ** SelectCommand ** . 指定 SQL 代码和参数 ,使用一或多条 SELECT 查询获取行集

· ** InsertCommand ** . 指定 SQL 代码和参数 于数据库中插入新行 .

· ** DeleteCommand. ** 指定 SQL 代码和参数 于数据库表中删除指定行集

· ** UpdateCommand. ** 指定 SQL 代码和参数 于数据库表中更新指定行集

如你所见 , ADO.NET 开发者们可以随意使用所有 SQL 代码获取或更改数据库中指定表中的数据 . 与经典的 ADO 操作不同他( ** DataAdapter ** )将在运行时创建查询操作 . 如是,我们可以使用 Microsoft® Visual Studio® .NET DataAdapter 配置向导 (DACW) 来创建一些或所有这些 命令匹配 . 这是一点更大的不同 . 当你比较 .NET 开发和基于 COM 的 Visual Studio 6.0 开发时 , 客户端处理的 " 黑盒 " 概念削弱了,因为更多的内容被包含在源文件中 . 这意味着如果你不喜欢向导生成的标准设计代码 , 你可以更改它 ( 具有风险 ).

** CommandBuilder ** 能够自动生成 SQL 代码减轻你编写查询命令的工作 , 将 ADO.NET Command 对象 , 和他们关联的 Parameters (参数集合)赋予 ** SelectCommand ** . 很好 . 他可以工作了 , 但只是在非常有限的情况下 , 他是有代价的 , 本文将论述这一问题 . 不同于 DACW, 代码和命令由 ** CommandBuilder ** 在背后创建 — 在另一个黑盒中 .

从基于 COM 的 ADO 升级

为了更好的对比 ADO.NET 与标准 ADO 的不同 , 让我们进一步探讨标准 ADO . 基于 COM 的标准 ADO (ADOc) 不存在 ** CommandBuilder ** , 或者至少不存在于表面上 . 他好像一个黑盒 处理查询动作 . ADOc 预先用过初始化 SELECT 查询来获取返回结果集所有描述的源数据 . 他降低了服务器端查询产生速度并使更新结果集的对象臃肿 但他不得不如此 . 因此 ADOc 是一个 OSFA (one size fits all 通用尺寸 ; 一个为各种情况设计的标准接口 ) OLE DB 接口 , 其他一些提供者无法提供这种能力 来提供 充分的 , 相容的 , 或 正确的源数据 . 这意味着他( ADOc )是 一个健壮的应用程序并能为更多支持者服务 .

ADOc 具有 ADO.NET CommandBuilder 不具备的 ** Update Criteria ** 属性 ( 参看 Microsoft Knowledge Base article 190727 ). 以我的观点 , 这是 ** CommandBuilder ** 一项重要的性能削弱 . Update Criteria 允许开发者 调整 ADOc 构造 SQL 命令动作 测试当前冲突 . 在此 , 基于 ** Update Criteria ** 属性已经设置 , SQL 查询动作根据如果服务器端数据行是否已经由于更新而改变来决定是否完成这个动作 . 例如 , 下面 ** Update Criteria ** 设置 决定你选择 的 SQL 命令如何运行 :

· ** AdCriteriaKey ** . 只用于主键 . 他表示如果行存在,更新或删除他 .

· ** adCriteriaAllCols ** . 构造 SQL 代码比较 Recordset (结果集)与服务器端所所有列数据 . 这与 ** CommandBuilder ** 很相似 .

· ** adCriteriaUpdCols ** . ( 默认值 ) 构造 SQL 代码比较,只对应结果集中更改的部分 .

· ** adCriteriaTimeStamp ** . 构造 SQL 代码比较,应用于 timestamp (时间戳) 列 ( 如果可用 ).

如你所见 , ADOc 和 ** Update Criteria ** 属性 允许你 决定是否 导入那些从未触及(或无法触及)的列集 . 这是非常重要的,因为这有许多情形下,在其他更新行集中你取了只读的列 . 例如 , 你的用户被允许读取 CurrentSalary 列 , 但 不允许更改它 . 没有类似的途径预防 ADO 中 UPDATE 声明的 SET 字句 , 你的应用程序将不得不使用其他方法 . 许多有力的并发验证技术几乎都 使用一个服务器准时间戳 列来发现 发送-接受 更改 . 典型的时间戳测试 , 服务器能够从你最后读取后行发生更改时立即告知你 . CommandBuilder 不能使用时间戳列管理并发 .

好了 , 结束冗长的论述 , ADO.NET CommandBuilder 不支持 ** Update Criteria ** 属性 . 他简单的使用粗糙的方法 ( 类似于 ** adCriteriaAllCols ** ) 来测试服务器端行的改变 . 这一问题使习惯于使用 ADO 并使用聪明方案的 ADOc 开发者感到失望 .

赋予 ADOc 更多的对获取源数据的控制和帮助 , 并且他为一些提供者性能更好 , Microsoft 寻找出 ADO.NET 骨架的雏形 . 这样可以理解为什么许多开发者不期望 使用 ADO 来只作他们的查询操作 总之 — 他们已经准备转移他们的查询操作逻辑到新的产品 . 使用 ADO.NET 他们必须要做很多 并绝对需要转换他们的角色 : 做到更轻、更快、更简单 . 构造 .NET 数据提供者也是一个重点 , 因此他无异于对 OLE DB 作一次脑外科手术 . 这个策略将为 ADO.NET 开发者减轻 SQL 动作查询的工作 .

ADO.NET CommandBuilder 如何工作

** CommandBuilder ** 需要你提供一个 正确的 , 可执行的 , 和标准的 ** SelectCommand ** 来与一个 ** DataAdapter ** 相关联 . 他也需要一个可行的连接 . 这是因为 ** CommandBuilder ** 打开连接与 ** DataAdapter ** 一同往返于服务器两端并且进行查询语句的构造 . 当完成时它会关闭连接 . 在你的应用程序中用代码构建一个 ** CommandBuilder ** 如下所示 :

** 清单 ** ** 1. ** ** 编制 ** ** CommandBuilder **

Dim cn As SqlConnection


Dim da As SqlDataAdapter


Dim cb As SqlCommandBuilder


cn = New SqlConnection("data source=demoserver…")


da = New SqlDataAdapter("SELECT Au_ID, au_lname, City FROM authors", cn)


cb = New SqlCommandBuilder(da)        ' 创建新的 CommandBuilder

从这段代码中你不知道背后作了什么 . 此时 , 如果你打开 Microsoft® SQL Server™ 日志 ( 当使用新编写的代码时这是一个好主意 ), 你无法知道 构造 ** CommandBuilder ** 作了些什么 , 从始至终 . 这是因为 ADO.NET 直到被应用程序调用前没有构造任何命令动作 . 例如 , 我在清单 1 中添加下列代码 ( 它为 ** UpdateCommand ** 获取 SQL 命令 ):

MsgBox(cb.GetUpdateCommand.CommandText.ToString)

ADO.NET 执行 :

exec sp_executesql N' SET FMTONLY OFF; SET NO_BROWSETABLE ON;_


   SET FMTONLY ON;SELECT au_ID, au_lname, city FROM authors'

<SPAN style="FONT-SIZE: 8pt; FONT-FAMILY: 宋体; mso-ascii-font-family: Verdana; mso-hansi

Published At
Categories with Web编程
Tagged with
comments powered by Disqus