rdoResultset 对象可以被定义为一系列的数据行,这些数据行可以通过游标访问也可以不通过。rdoEnvironment 或 rdoConnection 对象的 CursorDriver 属性决定了使用哪一种游标库,以及在哪里创建游标键集:在客户工作站还是服务器上。但是,OpenConnection 方法的 type 参数决定了游标将如何被创建。
选择了一种 type 参数设置之后,返回的结果集可以为以下几种类型:
结果集类型是根据数据源的 ODBC 接口的可用类型和功能来选择的。但是,如果将 CursorDriver 属性设置为 rdUseNone 的话,RDO 将不会为 rdoResultset 创建游标,它将永远(也仅仅)创建一个只能向前的、只读的、单行的、无游标的结果集。
如果需要快速检索数据并且使开销最小,可以使用只能向前的 rdoResultset。这种类型的结果集可以更新,但每次只显示一个数据行。它不创建游标键集,数据值也是静态的,当数据源的数据被更新时它保持不变。但是它的效率高,所以,重建一个该类型的 rdoResultset 的速度可能快于建立并保持一个键集类型的 rdoResultset。
除非使用了 rdConcurReadOnly 选项并将 RowsetSize 设为 1,否则 RDO 将创建一个游标来管理只能向前的结果集,这对性能会有影响。但是,如果选择 rdUseNone 作为游标驱动程序的话,那么依据缺省值将创建一个只能向前的、只读的、无游标结果集。
除了可以更新这一点以外,静态的 rdoResultset 与 Jet 快照类型的 Recordset 对象是类似的。在客户端或服务器端,该类型的游标按照所选的游标驱动程序创建数据行的静态副本。静态游标数据看起来是不能修改的,就是说,在打开并完全置入到游标之后,静态游标使用的结果集的成员资格、顺序和值通常都是固定的。如果其它用户对(包括同一个应用程序中的其它游标)数据行进行更新、删除或插入,该游标都不会觉察到,直至它关闭并重新打开为止。
键集类型的 rdoResultset 与 Jet dynaset 型的 Recordset 对象类似。在游标中建立并保存了键(实际上是书签),它存储在客户工作站或服务器中。在访问每一个数据行时,所保存的键就用来从数据源取当前数据值。对于键集驱动的游标而言,一旦完全置入到该键集之后,成员资格就固定了,在重建之前,影响成员资格的添加或更新操作不会影响 rdoResultset。
在某些 ODBC 数据源上,使用 AddNew 和 Edit 方法直接对键集游标进行的修改和添加都会包含到该结果集中。但是使用 Execute 方法的添加和修改却不会影响游标。与此有关的详细信息,请参阅服务器手册。
要建立一个键集驱动的游标,客户和服务器必须有足够的资源,以保存键和一批(与 RowsetSize 有关)数据行。
在使用可更新的键集游标或静态游标时,虽然可以用 AddNew 方法在数据库中添加数据行,但是,这个新行并不总是能够被添加到 rdoResultset 中,也就是说,有些游标库将数据行同时添加到游标和基本表中,有些却不然。下表总结了各种游标库如何实现键集游标和静态游标:
游标库 | 使用 AddNew 将数据行添加到游标中 |
rdUseIfNeeded (服务器端的) | 能 |
rdUseODBC (ODBC) | 不能 |
rdUseServer (服务器端的) | 能 |
rdUseClientBatch (客户端批处理) | 能 |
rdUseNone (无游标) | 无法使用 |
除了成员资格不固定、不支持书签以外,动态类型的 rdoResultset 和键集驱动的游标是一样的。因为 RDO 需要经常检查具有成员资格的所有的合格数据行,所以该类型游标的系统开销是最大的。但是,动态类型的游标的启动可能会比键集游标要快,因为创建键集游标时需要初始化键集。
通常情况下,要避免使用动态游标,因为它的实现和维护都是代价高昂的,也就是说,该类型的游标会用掉大量的 RAM,并且要求相当的网络带宽。
在首次创建一个键集类型的或静态类型的游标时,RowCount 属性被设置为:
当代码引用 RowCount 属性时,RDO 在将控制返回到应用程序之前完成 rdoResultset 的置入,对于数据行数可以改变的动态游标,以及只能显示一行数据的只能向前的结果集,RowCount 是无效的。
如果有一个未完成置入的 rdoResultset 在数据源上挂起,而该数据源只能支持 rdoConnection 对象上的一种操作,那么,在 rdoResultset 被刷新、关闭或完成置入之前,将不能创建另外的 rdoQuery 或 rdoResultset 对象,也不能对 rdoTable 对象使用 Refresh 方法。例如,如果使用 SQL Server 4.2 作为数据源,或使用 SQL Server 6.x 的客户端游标时,那么,在移到当前 rdoResultset 对象的最后一行之前,将不能创建另外的 rdoResultset 对象。为了完成结果集的置入,可以使用 MoreResults 方法遍历所有挂起的结果集,或对 rdoResultset 使用 Cancel 或 Close 方法,以刷新所有挂起的结果集。有的数据源可能没有这种局限性。如果需要提交一个查询,但是 hStmt 是无效的,那么必须打开另一个连接。
在通过改变 OpenResultset 方法的 LockType 选项更改数据时,可以控制数据源和选定的游标库如何管理行及页面的锁定。下表描述了四种类型的锁定。
LockType 选项 | 描述 |
rdConcurLock | 保守的并发。这种方法使用了最低级别的锁定,充分确保了数据行的更新。 |
rdConcurRowVer | 使用行版本的开放式的并发。ODBC 游标库和数据源通过比较行的 ID 或 TIMESTAMP 的值来确定行是否改动过。 |
rdConcurValues | 使用数据行值的开放式并发。ODBC 游标库和数据源对数据的值进行比较。 |
rdConcurReadOnly | 该游标是只读的。不允许任何形式的改动。 |
rdConcurBatch | 使用客户端的批游标库,并且,在使用 BatchUpdate 方法之前,推迟所有的更新。 |
注意 rdConcurLock 选项将锁定由 RowsetSize 属性设定的所有行集合。这种锁定在结果集打开后立即创建,而不是等到执行 Edit 方法之后。因为行集合是要重定位的,与该行集合有关的数据行和页将被锁定,其余的则被释放。由于这种机制,仅仅在特殊情况下才使用保守的锁定。
使用开放式锁定时,通过对比行数据值和行版本来检查并发。在这种情况下,将使用 Edit 和 AddNew 方法之前的原始行与通过 Update 方法更改之前的数据行进行对比。如果这时行数据发生了改变的话,将导致一个可以捕获的错误。这时,临时的行缓冲区将被丢失。要执行这些修改,必须使用 Move 0 方法刷新当前行,然后使用 Edit 或 AddNew 方法填入新值,并再次使用 Update 方法。