ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

ADO 对象游标类型实战:Connection、RecordSet 与 Adodc 显示数据记录的三板斧

ADO 对象游标类型实战:Connection、RecordSet 与 Adodc 显示数据记录的三板斧 1. 为什么你的 ADO 查询有时快有时慢还读不到 RecordCount很多人第一次接触 ADO 时都会遇到一个很迷惑的现象同一段查询代码换个数据库、换个写法RecordCount一会儿返回真实条数一会儿返回 -1MoveNext能跑MovePrevious却直接报错明明数据库里刚改过的数据程序读出来还是旧的。这些问题的根源八成不在 SQL 语句而在**游标类型CursorType和游标位置CursorLocation**这两个属性上。ADO 这套数据访问模型里Connection负责建立通道RecordSet负责承载结果集而游标就是结果集在内存和数据库之间的“取数策略”。CursorLocation决定游标由谁提供客户端本地库还是数据库驱动CursorType决定结果集能不能滚动、能不能看到别人的修改LockType决定你改数据时别人能不能同时改。三者组合起来才决定了你这段代码的实际行为。这篇内容面向还在维护经典 VB6、VBA、ASP 老项目的同学也适合刚学 ADO 想搞懂游标差异的新手。我会把Connection与RecordSet的游标类型差异讲清楚再结合Adodc控件演示数据记录显示的三种典型做法每一步都给可复制的连接字符串、属性配置片段和验证动作。跟着做你能在半小时内把数据展示流程跑通并且知道每个参数为什么这么设。2. 先把 TaoToken 的接入信息准备好在动手写 ADO 代码之前如果你打算用大模型辅助排查这些老项目的报错、生成连接字符串或者解释游标行为可以先把 TaoToken 的接入信息配好。它的官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 注意 API 地址不带 UTM 参数。接入前你需要先拿到密钥这一步在控制台的 API Keys 页面完成https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。拿到 Key 之后如果你只是想验证某个游标参数的含义、让模型帮你解释一段报错可以直接在模型对话页测试https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果你是要长期写代码、做 Agent 类任务建议看 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite Claude Code 相关的说明在 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite 。提示TaoToken 在这里的角色是帮你解释游标行为、生成和校对连接字符串、排查报错的辅助工具不是替代你的数据库或编辑器。真正的数据访问逻辑还是跑在你自己的 ADO 代码里。3. Connection 与 RecordSet 的游标类型差异3.1 CursorLocation游标到底由谁提供Connection对象上有一个CursorLocation属性它表示游标服务程序的默认位置。关键点是这个值会被使用该 Connection 的 Recordset 对象自动继承。也就是说你在 Connection 上设一次后面 Open 出来的 RecordSet 默认就用这个位置除非你在 RecordSet 上单独覆盖。常用的两个值常量值含义典型影响adUseClient3使用本地游标库提供的客户端游标支持 RecordCount、可断开连接、功能全但数据要全传到本地adUseServer2默认值使用数据提供者或驱动提供的游标取数快、对数据源改动敏感但部分功能受限adUseClientBatch与adUseClient同义属于向后兼容的写法。用adUseClient时数据需要先传输到客户端再操作它不具有同步性如果你执行查询后、在取结果前有另一个程序改了数据库客户端拿到的还是改动之前的数据。好处是它能更好地支持RecordCount这类属性因为全部数据已经在本地程序能确切知道有多少条。代价是性能数据量大时尤其明显必须全部执行完再传回客户端。adUseServer直接在数据库上操作拿到指向数据的游标后就返回处理速度更快具体数据等到调用MoveNext之类方法时才运算。但限制也多比如在遍历结果集之前程序无法知道结果集到底有多少条数据RecordCount往往返回 -1。3.2 RecordSet 的 CursorType能不能滚动、能不能看到最新数据RecordSet上的CursorType决定结果集的滚动能力和数据新鲜度。四种常用类型常量值滚动能力数据新鲜度备注adOpenForwardOnly0只能 MoveNext打开时建立备份不能即时体现编辑增删默认最快adOpenKeyset1可上下滚动能看到修改但看不到别人新增/删除维护关键字列表adOpenDynamic2完全可滚动能看到最新状态效率较低adOpenStatic3完全可滚动打开时备份可断开连接后继续用静态快照adOpenForwardOnly只能用MoveNext读取打开的同时建立了数据库的备份不能即时体现记录的编辑和增删。adOpenKeyset给打开的记录创建了一个关键字列表类似记录集的描述访问时才去取值所以能即时看到修改信息但看不到数据是否被删除因为关键字列表是事先初始化好的。adOpenDynamic完全可滚动能得到数据最新状态执行效率也会降低。adOpenStatic完全可滚动和adOpenKeyset类似先备份再操作可以断开数据库连接后继续使用。3.3 LockType改数据时别人能不能同时改锁类型决定并发行为四种常用值常量值含义适用场景adLockReadOnly1只读锁不能操作记录纯读取adLockPessimistic2悲观锁打开即上锁直到修改完成更新单条记录adLockOptimistic3乐观锁更新时才上锁一般更新adLockBatchOptimistic4批量乐观锁批量更新需可滚动游标不需要更新数据的读取操作推荐adLockReadOnly。添加删除更新一条记录时推荐adLockPessimistic防止你在更新一条记录时其他人操作同一条记录或同时录入不合法的重复记录。比如用户名注册在查重和提交新名称之间有间隔悲观锁能防止间隔期其他用户提交你已通过查重的合法名称或录入两个相同名称。adLockBatchOptimistic在 SQL Server 中使用时必须打开一个可上下滚动的游标比如adOpenKeyset或adOpenStatic。4. 可复制的连接字符串与游标配置片段4.1 ASP 读取场景只读 客户端游标读取数据库时如果你需要RecordCount和分页用客户端游标加只读锁% Dim conn, rs, strcn, strsql strcn ProviderSQLOLEDB;Data Source127.0.0.1;Initial CatalogTestDB;User IDsa;Password你的密码; Set conn Server.CreateObject(ADODB.Connection) conn.CursorLocation 3 adUseClient conn.Open strcn strsql SELECT ID, UserName, CreateTime FROM Users ORDER BY ID Set rs Server.CreateObject(ADODB.Recordset) rs.Open strsql, conn, 3, 1 adOpenStatic, adLockReadOnly Response.Write 总记录数 rs.RecordCount %这里rs.Open的第三个参数是 CursorType第四个是 LockType。用adOpenStatic配合adUseClientRecordCount能返回真实条数。4.2 ASP 更新场景悲观锁防并发更新数据库时用悲观锁防止并发覆盖% Set rs Server.CreateObject(ADODB.Recordset) rs.Open SELECT * FROM Users WHERE ID1001, conn, 1, 2 adOpenKeyset, adLockPessimistic If Not rs.EOF Then rs(UserName) 新名字 rs.Update End If rs.Close Set rs Nothing %注意这里 CursorType 用adOpenKeyset值 1LockType 用adLockPessimistic值 2。打开后立即上锁直到修改完成或放弃其他人无法编辑这条记录。4.3 VB6 中 Adodc 控件的连接配置在 VB6 窗体上拖入Adodc和DataGrid然后配置Private Sub Form_Load() Dim strcn As String Dim strsql As String strcn ProviderSQLOLEDB;Data Source127.0.0.1;Initial CatalogTestDB;User IDsa;Password你的密码; strsql SELECT ID, UserName, CreateTime FROM Users ORDER BY ID Adodc1.ConnectionString strcn Adodc1.CommandType adCmdUnknown Adodc1.RecordSource strsql Adodc1.CursorLocation adUseClient Adodc1.CursorType adOpenStatic Adodc1.LockType adLockReadOnly Set DataGrid1.DataSource Adodc1 Adodc1.Refresh DataGrid1.Refresh End SubAdodc和DataGrid是一对配合使用的组合Adodc负责数据源DataGrid负责显示。设置DataSource后调用Refresh数据就会显示出来。5. 验证请求与成功结果5.1 验证 RecordCount 是否返回真实条数在 ASP 里跑上面 4.1 的代码如果页面输出“总记录数25”这样的真实数字说明adUseClientadOpenStatic生效了。如果输出 -1说明游标位置或类型不对检查conn.CursorLocation是否设成了 3。5.2 验证滚动能力% If rs.RecordCount 0 Then rs.MoveLast Response.Write 最后一条 ID rs(ID) rs.MoveFirst Response.Write 第一条 ID rs(ID) End If %如果MoveLast报错“当前游标不支持向后滚动”说明你用的是adOpenForwardOnly换成adOpenStatic或adOpenKeyset即可。5.3 验证 Adodc 显示运行 VB6 程序如果DataGrid里出现了数据行并且列头是ID、UserName、CreateTime说明Adodc配置成功。如果DataGrid空白检查Adodc1.Refresh是否在Set DataSource之后调用以及连接字符串里的密码是否正确。6. 本篇常见错排查6.1 RecordCount 返回 -1最常见的原因是用了adUseServer游标。服务器端游标在遍历前不知道总条数所以返回 -1。解决办法是把Connection.CursorLocation设为adUseClient值 3并把CursorType设为adOpenStatic或adOpenKeyset。6.2 MovePrevious 报错adOpenForwardOnly只支持MoveNext调用MovePrevious会报错。把CursorType改成adOpenStatic值 3或adOpenKeyset值 1即可。6.3 更新时提示“无法更新游标不支持”adLockReadOnly的游标不能更新。把LockType改成adLockPessimistic值 2或adLockOptimistic值 3。如果用的是adLockBatchOptimistic还要确保CursorType是可滚动的比如adOpenKeyset。6.4 Adodc 连接字符串报错检查Provider是否正确。SQL Server 用SQLOLEDBAccess 用Microsoft.Jet.OLEDB.4.0。如果密码里有特殊字符注意转义。另外CommandType设为adCmdUnknown时RecordSource直接写 SQL 语句即可。6.5 数据读出来是旧的如果你用的是adOpenStatic或adOpenForwardOnly打开时建立了备份之后数据库的改动不会反映到结果集。需要看到最新数据用adOpenDynamic值 2或者重新打开 RecordSet。7. 继续排查与接入如果你在配置游标类型时遇到报错或者想让模型帮你解释某段 ADO 代码的行为可以先去 API Keys 页面拿到密钥https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 然后对照接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 把请求发出去。验证某个游标参数的含义直接在模型对话页试https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果你是要长期维护老项目、写大量 ADO 相关代码Coding Plan 会更合适https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后留一个我踩过的坑在 ASP 里用adUseClient时如果结果集很大页面会明显变慢因为数据全部传到了客户端。这种场景下分页查询配合adOpenForwardOnly反而更稳。游标类型没有绝对的好坏只有适不适合你当前的读取和更新需求。
返回列表