📄 7277.htm
字号:
<li>通过快速、仅向前的只读游标来滚动数据,这种游标工作在记录的静态快照中。ado 称之为只读游标。<br><br>
<li>通过服务器端的两种游标来访问数据,这些游标需要保持良好的连接,但您可以在各个不同层次上随时检测其他已连接的用户的更改。ado 称它们为键集和动态游标。 </li></ul>
<p>前两种方式都在断开连接的记录集内工作,并从客户端缓存读取信息,这是它们的相似之处。另外,在面向 web 的环境中和对于新的 <i>n</i> 层系统,这两种方式被证明是使用频率最高的。</p>
<p>在 ado 中,以上所有这些方式与不同类型的游标相对应。您将在本文后面发现,虽然 ado.net 有很大不同,但它能实现您用 ado 可实现的任何功能。只不过您的代码将从实际数据源及其物理存储媒介和格式中抽取数据。</p>
<p>ado.net 提供两个对象来处理从数据源中抽取的数据。它们是 <b>dataset</b> 和 <b>datareader</b> 对象。前者是记录在内存中的缓存,您可以从任何方向随意访问和修改。后者是高度优化的对象,专为以仅向前方式滚动只读记录而设计。请注意 <b>dataset</b> 看起来象静态游标,但实际上,在 .net 中与 ado 只读游标相对应的是 <b>datareader</b> 对象。</p>
<p>在 ado.net 中,不支持服务器端游标。然而,这不意味着您不能使用游标。您需要做的是在 .net 中导入 ado 类型库。在项目窗口的 <b>references</b> 节点上单击右键就行了。导入之后,您便可以开始在应用程序中使用本地 ado 对象了。</p>
<p>尽管我承认下决心转向 .net 是一件很难的事情,但我个人还是建议您考虑用 .net 重写现有应用程序。可以把完全导入 ado 作为迈向 .net 的第一步,这无须投入太多的时间和资源。然而,请记住这只是漫漫长路上的第一步。这绝不是您迈向 .net 的唯一一步。.net 具有超值价值的的真正原因在于统一和一致的编程接口以及对本地类的广泛使用。您可以导入 com 类型库,但导入 com 类型库只能作为临时解决方案或者中间步骤,我们并不鼓励这样做。</p>
<p>使用 ado.net 时,应当充分考虑到它统一了数据容器类编程接口这一事实。无论您打算编写何种应用程序,windows 窗体、web 窗体还是 web 服务,都可以通过同一组类来处理数据。不管在后端的数据源是 sql server 数据库、ole db、xml 文件还是一个数组,您都可以通过相同的方法和属性来滚动和处理它们的内容。</p>
<p><img alt="" src="adonetdev01.gif" border=0></p>
<p class=label><b>图 1:solution explorer 菜单</b></p>
<p>如果您坚持在 .net 中使用 ado,请准备面对一些副作用。例如,您需要额外的代码才能够从数据绑定控件中使用记录集。</p>
<h2><a name=adonetdev_topic3></a>dataset、datatable 和 recordset</h2>
<p>在 ado.net 中,没有与 <b>recordset</b> 对象直接对应的对象。最接近的是 <b>datatable</b> 对象。尽管这两个对象的功能几乎一样,但它们在各自的框架中起不同的作用。</p>
<p><b>recordset</b> 是一个大型对象,具有许多 ado 功能,但还是有所欠缺。<b>recordset</b> 在很多方面性能优良,例如可创建性、断开连接时仍能工作、功能丰富等等。但是,在某些方面仍然有待提高。例如,由于 <b>recordset</b> 固有的 com 特性,通过网络进行序列化的工作将非常繁重。又如它是二进制对象,所以在不同的平台上运行的模块很难共享它,而且它不能穿过防火墙。另外,<b>recordset</b> 表示多个记录的单个表。如果该表是由一个或多个 join 产生的,更新原始数据源可能会很困难。如果您要使断开连接的记录集和原始数据源保持协调,数据源必须能够识别 sql。然而,您的记录集很可能是通过非 sql 提供程序创建的。</p>
<p>在 ado.net 中,ado recordset 的所有功能被拆分成几个较简单的对象,<b>datareader</b> 就是其中之一。<b>datareader</b> 模拟快速、仅向前的只读游标的操作。</p>
<p><b>datatable</b> 是一个表示数据源的简单对象。您可以手动构造 <b>datatable</b>,也可以通过 <b>dataset</b> 命令自动填充它。<b>datatable</b> 不区分它所包含的数据的来源。该对象允许您在内存中处理数据,以及执行浏览、排序、编辑、应用筛选器、创建视图等操作。</p>
<p>ado 中没有与 <b>dataset</b> 相对应的对象。<b>dataset</b> 对象是一个容器类,是实现 ado.net 数据抽取的关键对象。<b>dataset</b> 将一个或多个 <b>datatable</b> 对象分组。<b>datatable</b> 通过象行和列这样的通用集合公开它的内容。当您尝试从数据表中读取数据时,您可能会经过两个不同的对象层:<b>datatablemapping</b> 和 <b>dataview</b>。</p>
<p><b>datatablemapping</b> 对象描述了数据源中的数据列和 <b>datatable</b> 对象之间的映射关系。当填充 <b>dataset</b> 时,<b>datasetcommand</b> 对象要使用这个类。它维护数据集中的抽象列和数据源中的物理列之间的链接。</p>
<p>表的视图通过 <b>dataview</b> 对象实现。它表示 <b>datatable</b> 的自定义视图,可以绑定到特定控件(如 windows 窗体和 web 窗体中的数据网格)中。该对象相当于 sql create view 语句在内存中的实现。</p>
<p><b>dataset</b> 中的所有表都可以通过一个公用域放入关系中。这个关系由 <b>datarelation</b> 对象管理。这看起来很象 ado 的数据形成,但有一点重要区别。您不需要使用数据形成语言,您最终会拥有一个非常灵活的结构体系。ado.net 导航模型使您可以轻而易举地从某一张表内的主行移入它的所有子行。</p>
<p><b>datarelation</b> 对象相当于 join 语句在内存中的实现,可用于建立数据类型相同的列的父/子关系。一旦建立了关系,就不允许出现任何会破坏这种关系的更改,如果出现就会导致运行时异常。视图和关系是实现主表/明细表架构的两种方式。要记住,视图只是放在记录上的掩码,而关系是设置在两个表的一个或多个列之间的动态链接。如果使用关系,您不能更改顺序或设置条件。</p>
<p>如果您的代码需要一对一外键关系,并且不更改数据,那么您最好不要使用无格式的 join 命令。如果您需要额外的筛选功能,就应该使用 ado.net 自定义视图。</p>
<h2><a name=adonetdev_topic4></a>转换现有代码</h2>
<p>有许多 asp 页面使用 ado 对象来抽取数据。让我们来讨论几种典型的情况,您在不久的将来移植和改编代码时可能会遇上这些情形。</p>
<p>如果您有从单个记录集生成报表的 asp 页面,<b>datareader</b> 对象将是您最好的伙伴。<br>您浏览 <b>datareader</b> 对象时,它会将结果输出到页面。</p><pre><code>string strconn, strcmd;
strconn = "database=myagenda;server=localhost;uid=sa;pwd=;";
strcmd = "select * from names where id=" + contactid.text;
sqlconnection ocn = new sqlconnection(strconn);
sqlcommand ocmd = new sqlcommand(strcmd, ocn);
ocn.open();
sqldatareader dr;
ocmd.execute(out dr);
while (dr.read()) {
// 使用 dr.getstring(index) 或
// dr["field name"] 的方法 response.write 来输出数据
}
</code></pre>
<p>您还可以用 <b>hasmorerows</b> 属性快速检查 <b>datareader</b> 是否为空。如果您只需要快速浏览一系列记录,没有比 <b>datareader</b> 更好更快的对象了。它同样适用于查询单个记录。您不能编辑 <b>datareader</b> 的内容,但您可以将其内容移入更易于管理的对象,例如 <b>datatable</b> 或者一个或多个 <b>datarow</b> 对象。</p>
<p>当您需要处理表和记录之间的复杂关系时,datareader 就不再是合适的工具了。在 ado 中, 最终您需要处理记录集。您的数据模型链接越多,sql 命令就越复杂。导航模型仍然是顺序的,最后放入缓存的数据往往多于你所需要的。<b>dataset</b> 和 <b>datarelation</b> 对象是这种表关系模型的基础。</p>
<p>为了管理父/子关系,ado 还封装了数据形成引擎。从功能上讲,数据形成和 ado.net 关系是一样的。然而,从设计方面来看,它们几乎没有什么共同点。形成记录集将所有信息嵌入单个列表对象。ado.net 关系是您可以随时在两个数据表之间建立的动态链接。为了在执行单个 ado 命令的过程中创建一个层次结构记录集,ado 要依靠 shaping ole db 服务提供程序,并且使用特定的类 sql 语言。</p>
<p>在 ado.net 中,关系中涉及的每个对象总是被看成单独的个体。关系本身作为对象被公开,并且具有一定的行为规则。例如,<b>datarelation</b> 对象可以从父行到子行一层层进行更改。您可以通过将 <b>foreignkeyconstraint</b> 对象添加到 <b>datatable</b> 的 <b>constraints</b> 集合中来进行此操作。<b>foreignkeyconstraint</b> 对象表示当删除或更新数值和行时,对通过外键关系相关联的一组列的约束。如前面提到的,一旦设置好了关系,在它按程序预设终止之前,您不能进行可能破坏该关系的更改。</p>
<p>另外,关系是不可传递的。您可以建立两组不同的关系,例如客户和订单、订单和产品之间的关系。然而,当在订单中导航以寻找某一位客户时,您不能从一个订单跳到与之相关的产品行。您必须另外打开订单/产品关系,定位到您需要的订单,然后才能获取相关的行。这就是为什么有时候最好不要通过原来的无格式 sql join 语句实现一对一关系的原因。</p>
<p>需要在 asp session 对象中存储记录吗?利用 ado.net 和 <b>dataset</b> 对象,您可以相当安全的操作而不会导致在<a href="http://support.microsoft.com/support/kb/articles/q249/1/75.asp">在 git 中存储 ado 记录集可能会导致访问冲突</a>(英文)中所讨论的问题,也不会有线程相似性的麻烦。</p>
<h2><a name=adonetdev_topic5></a>更新数据</h2>
<p>更新数据时,web 应用程序通常使用无格式 sql 语句,或者使用更好的参数化存储过程。然而,当需要使用未连接的数据时,您可能想使用内置服务来更新所有需要修订的记录。ado 提供了批更新机制来实现这个功能。</p>
<p><b>updatebatch</b> 方法用于把保存在副本缓冲中的 <b>recordset</b> 更改发送到服务器,以更新数据源。它采用开放式锁定,允许所有挂起的本地更改。它还在单个操作中把所有更改传送到数据源。仅当更改提交后数据源锁定要更改的记录时,才会出现开放式锁定。开放式锁定使两个用户可以同时访问同一个记录,但一个用户输入的更改很快会被另一用户所覆盖。当然,这种方式要求数据源能够检测和防止数据冲突。还要求整个数据源比较稳定,不会发生频繁的更改。否则,不难想象协调费用将很快超过替代严格锁定所带来的节约。事实上,使用 <b>updatebatch</b> 方法,在任何更改失败时都会返回一个错误。然后,您可以通过 <b>errors</b> 集合和 <b>error</b> 对象来访问该错误。</p>
<p>要理解 ado.net 模型为什么是更新数据的更强大的工具,理解 ado 中开放式锁定的工作原理是非常关键的。在 ado 代码中,您无法控制调用 <b>updatebatch</b> 之后所发生的一切。也就是说,更新是在服务器上通过滚动已更改的行,然后比较原始值和数据源中对应记录中的当前值来进行的。当所有的值都一致了,才对表执行适当的 sql 语句(insert、update 或 delete)。</p>
<p>问题在于您不能控制实际应用于更改的 sql 语句。服务器端的更新代码并不比您编写的代码好,如果您采用非 sql 提供程序,它甚至无法运行。在本节的开头,我曾讲过 web 应用程序通常通过参数化存储过程来更新数据。然而,如果您使用批更新就不同了。</p>
<p>在 ado.net 中,这个模型已经有所扩展。现在它采用更通用的架构,允许您自己指定基本操作命令,例如插入、删除、更新和选择等。其用意很明显:不论何种数据源,都可以从中抽取数据并提供同样的支持。在 ado.net 中进行批更新,您需要创建 <b>datasetcommand</b> 对象即 <b>sqldatasetcommand</b> 或 <b>adodatasetcommand</b>。</p>
<p class=indent><b><b>注意:</b></b>在 beta 2 中,<b>datasetcommand</b> 对象将被称为 <b>dataadapter</b> 对象。</p>
<p>拥有 <b>datasetcommand</b> 对象之后,您便可以调用它的 <b>update</b> 方法。<b>datasetcommand</b> 提供 <b>insertcommand</b>、<b>deletecommand</b>、<b>updatecommand</b> 和 <b>selectcommand</b> 等属性。它们都是 <b>command</b> 对象。但是,除非默认行为无法满足需要,否则您不必设置它们。这与在 ado 中一样。在 <b>update</b> 过程中,如果没有设置任何 xxxcommand 属性,但是存在主键信息,将自动生成 <b>command</b> 对象。请注意,要使上述过程正确进行,必须为所涉及的数据表设置主键。</p>
<p>以下代码显示了如何为 dataset 的 employeeslist 表设置主键:</p><pre><code>datacolumn[] keys = new datacolumn[1];
keys[0] = m_ods.tables["employeeslist"].columns["employeeid"];
m_ods.tables["employeeslist"].primarykey = keys;
</code></pre>
<p>主键基本上是 <b>datacolumn</b> 对象的一个数组。</p>
<p>如果您要使用存储过程来更新表,或者采用专用非 sql 数据提供程序,您会经常用到这些命令属性。</p>
<h2><a name=adonetdev_topic6></a>xml 扩展支持</h2>
<p>在 ado 中,xml 只不过是输入和输出格式。然而在 ado.net 中,xml 是一种数据格式,提供了操作、组织、共享和传递数据的手段。任何带入 <b>dataset</b> 的数据,无论其来源,都能通过双面编程模型进行处理。您可以顺序交替访问信息,或者按行访问,也可以按照 xml 文档对象模型驱动的非顺序、层次结构路径进行访问。</p>
<p><b>dataset</b> 将数据和架构作为 xml 文档进行读写。数据和架构都可以通过 http 传输,并且能在所有支持 xml 的平台上使用。相同的数据在不同的时候可以通过不同的架构来呈现,这是通过 xslt 实现的。您可以使用 <b>readxmlschema</b> 方法编写架构。xml 架构包括数据集中的表的说明,以及表的关系和约束。在调用 <b>readxmldata</b> 方法填充 <b>dataset</b> 之前,应该先完成这个步骤。</p>
<p>以下代码示例是一个显示可更新数据表的最简单的 asp.net 页面。</p><pre><code><%@ import namespace="system.data" %>
<%@ import namespace="system.io" %>
<script runat="server" language="c#">
void page_load(object source, eventargs e)
{
dataset data = new dataset();
// 加载 xml 数据和架构
streamreader sr;
sr = new streamreader(server.mappath("data.xml"));
data.readxml(sr);
sr.close();
// 添加通过 url 传递的新记录
if (request.querystring.count >0)
{
datatable dt = data.tables[0];
datarow dr = dt.newrow();
dr["firstname"] = request.querystring["first"];
dr["lastname"] = request.querystring["last"];
dt.rows.add(dr);
dt.acceptchanges();
streamwriter sw;
sw = new streamwriter(server.mappath("data.xml"));
data.writexml(sw);
sw.close();
}
// 刷新 ui(由网格组成)
grid.datasource = data.tables[0].defaultview;
grid.databind();
}
</script>
</code></pre>
<p>如图 2 所示,您可以将新的行添加到表中。然而,它不涉及 sql server 或 access 表。它只是一个 xml 文件,在处理它的代码中,没有使用 xml 节点或 <b>xmldom</b> 方法。您可以用相同的直观数据表接口来读取和更新 xml 记录。您的工作方式与在 ado 中大致相同,但此处的模型更深入、更庞大,有更多的潜力供您去发掘。</p>
<p><img alt="" src="adonetdev02.gif" border=0></p>
<p class=label><b>图 2:可更新表的示例</b></p>
<h2><a name=adonetdev_topic7></a>总结</h2>
<p>web 应用程序的成功改变了典型分布式系统的面貌。现在大多数分布式系统都是 <i>n</i> 层系统,这类系统对扩展性和互操作性的要求越来越高。因此,非连接数据处理和 xml 成为最佳实践,并为业界广为接受。 </p>
<p>ado.net 尝试将当今一些最好的实践统一在 .net 下。这种用于数据访问的编程模型全面而又非常强大。但这个模型可能尚不能满足每一个人的要求,在将来的模型设计中还需要迈出一大步。然而,请记住现在 ado.net 还只是 beta 版,只有有限的文档支持。</p>
<p>ado 程序员从 beta 版中获益最多,因为他们熟悉了 ado.net 的许多方面,包括最高层次的抽象即启发性模型。ado.net 代码与现有的 ado 代码不兼容,但功能相似。要充分利用 ado.net,您应该花些功夫来理解概念本身,而不仅仅是找出移植代码的最快方式。无论您选择何种 .net 编程模型,windows 窗体、web 窗体还是 web 服务,ado.net 都会帮助您处理好数据访问的问题。</p><!--- end main ---><!--- end ---></font><br><br>
</DIV></div></div>
<script src='../../../get_readnum.asp?id=
7277
'></script>
</center></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -