ARTICLE DETAIL

资讯详情

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

Recordset.Open 方法参数详解:从 CursorType 到 LockType 的配置骨架与验证

Recordset.Open 方法参数详解:从 CursorType 到 LockType 的配置骨架与验证 1. 为什么 Recordset.Open 的参数总让人踩坑Recordset.Open 是 ADO 数据访问里最常被调用、也最容易被忽略的一个方法。很多人写 ASP 或 VB 的时候习惯性地只传前两个参数后面三个全部走默认值代码能跑通就再也不管了。结果等到分页查询变慢、多人同时改一条记录出现覆盖、或者RecordCount返回 -1 的时候才开始回头翻文档。Recordset.Open 方法参数详解这件事本质上不是背常量表而是搞清楚每个参数如何影响游标行为和并发控制。这篇文章面向的是还在维护传统 ASP/VB 数据访问代码的开发者或者正在学习 ADO 这套老技术栈的人。我会把 Source、ActiveConnection、CursorType、LockType、Options 五个参数逐个拆开给出可以直接复制的配置骨架再配上逐项的验证动作。你不需要死记常量值但需要知道什么场景该配什么组合以及配错了会报什么错。先说结论CursorType 决定你能不能前后滚动、能不能看到别人改的数据LockType 决定你改数据时会不会锁住别人、会不会被别人覆盖。这两个参数是 Recordset.Open 的灵魂Source 和 ActiveConnection 反而是最直观的。Options 则是给 Source 传非 SQL 内容时的补充说明。下面按这个顺序展开。2. TaoToken 前置把模型对话和 Key 管理准备好在动手写 ADO 代码之前我习惯先把调试环境搭好。传统 ASP/VB 的报错信息往往很含糊比如ADODB.Recordset 错误 800a0bb9这种光看错误码很难定位是参数类型不对还是提供者不支持。这时候用一个大模型对话工具来辅助解读错误码、生成对照代码效率会高很多。TaoToken 的模型对话入口可以直接问「AdOpenKeyset 和 AdOpenStatic 在分页场景下的区别」它会结合上下文给出可运行的示例。地址是 https://taotoken.net/api 模型对话的 deep link 是 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel-chat 。如果你要长期写这类数据访问代码甚至想让 Agent 帮你批量重构老 ASP 文件可以看 Coding Plan https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding-plan 。Key 的获取在控制台的 API Keys 页面 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi-keys 。接入文档在 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc 。这一步不是必须的但当你被Arguments are of the wrong type这类报错卡住时有个能对话的工具会省不少时间。3. 可复制配置五个参数的骨架与取值对照3.1 Source 与 ActiveConnection 的传参形态Source 是变体型可以传 SQL 语句、表名、存储过程名、Command 对象变量或者持久化 Recordset 的文件名。ActiveConnection 可以传已打开的 Connection 对象变量也可以直接传连接字符串。这两种写法在行为上有细微差别传 Connection 对象时Recordset 关闭后连接仍然可用传字符串时ADO 会自己创建一个连接Recordset 关闭后连接也随之释放。 写法一复用已打开的 Connection 对象 Dim conn, rs Set conn Server.CreateObject(ADODB.Connection) conn.Open ProviderSQLOLEDB;Data Source.;Initial CatalogTestDB;UIDsa;PWDxxx; Set rs Server.CreateObject(ADODB.Recordset) rs.Open SELECT id, name FROM users, conn, 1, 1 写法二直接传连接字符串Recordset 自管理连接 rs.Open SELECT id, name FROM users, _ ProviderSQLOLEDB;Data Source.;Initial CatalogTestDB;UIDsa;PWDxxx;, _ 1, 1实测下来写法一在需要多次查询时更省资源因为连接只开一次。写法二适合一次性查询代码更短但每次 Open 都会新建连接高频调用时开销明显。3.2 CursorType 取值对照与行为差异CursorType 决定游标的移动能力和数据可见性。默认值是 0AdOpenForwardOnly只能向前遍历RecordCount返回 -1MovePrevious会报错。很多人分页时发现拿不到总记录数就是因为用了默认值。值常量移动能力数据可见性典型场景0AdOpenForwardOnly仅向前快照式只读列表、逐行输出1AdOpenKeyset自由移动能看到他人修改的值看不到新增行需要翻页且数据会变2AdOpenDynamic自由移动能看到增删改实时性要求高3AdOpenStatic自由移动打开时的快照分页统计、离线分析 需要 RecordCount 和分页时用静态游标 rs.Open SELECT id, name FROM users ORDER BY id, conn, 3, 1 Response.Write 总记录数 rs.RecordCount注意AdOpenDynamic 在 SQL Server 的 OLE DB 提供者下支持有限某些场景会被降级为 Keyset不要盲目依赖它的实时性。3.3 LockType 取值对照与并发控制LockType 决定你编辑记录时如何锁定数据源。默认值是 1AdLockReadOnly此时rs.Update会直接报错。要改数据至少得用 3AdLockOptimistic。值常量锁定时机并发影响1AdLockReadOnly不锁定只读无法更新2AdLockPessimistic编辑时立即锁别人无法同时改容易阻塞3AdLockOptimistic调用 Update 时才锁并发较好但可能覆盖4AdLockBatchOptimistic批量更新时锁适合离线批量改 乐观锁更新只在 Update 时锁定适合低冲突场景 rs.Open SELECT id, name FROM users WHERE id1, conn, 1, 3 rs(name) 新名字 rs.Update保守式锁定2在 Web 场景下要慎用因为用户打开编辑页到提交之间可能间隔很久记录一直被锁着别人全被堵住。乐观锁3更常见但需要自己处理「更新时数据已被他人修改」的情况。3.4 Options 的取值与使用时机Options 是长整型告诉提供者如何解释 Source。常见取值1 表示 Source 是 SQL 文本AdCmdText2 表示表名AdCmdTable4 表示存储过程AdCmdStoredProc512 表示 Source 是持久化 Recordset 的文件名AdCmdFile。Const adCmdText 1 Const adCmdStoredProc 4 明确告诉提供者这是存储过程调用 rs.Open usp_GetUsers, conn, 3, 1, adCmdStoredProc不传 Options 时提供者会自己猜 Source 的类型猜错就会报错或走低效路径。显式传值能避免这类问题尤其是存储过程名和表名容易混淆的时候。4. 验证请求逐项确认参数生效4.1 验证 CursorType 是否生效打开后立刻检查rs.CursorType属性看提供者实际采用的是不是你指定的值。有些提供者会降级比如你请求 Dynamic它给你 Keyset。rs.Open SELECT id FROM users, conn, 2, 1 Response.Write 请求的游标类型2实际 rs.CursorType 如果输出不是 2说明提供者降级了再验证移动能力rs.MoveLast后rs.MoveFirst如果报错说明是仅向前游标。rs.RecordCount如果返回 -1同样说明游标不支持计数。4.2 验证 LockType 是否生效rs.Open SELECT id, name FROM users WHERE id1, conn, 1, 3 Response.Write 锁定类型 rs.LockType rs(name) 测试值 On Error Resume Next rs.Update If Err.Number 0 Then Response.Write 更新失败 Err.Description Else Response.Write 更新成功 End If如果 LockType 是 1Update 会报ADODB.Recordset 错误 800a0cb3 当前记录集不支持更新。这个错误信息很明确看到就知道是 LockType 配错了。4.3 验证 Options 是否被正确解析传存储过程时如果 Options 没写对提供者可能把存储过程名当成表名报「对象不存在」。显式传 4 之后再用rs.ActiveConnection确认连接正常基本就能定位问题。5. 本篇常见错排查错误一ADODB.Recordset 错误 800a0bb9 参数类型不正确或不在可以接受的范围之内这个错误九成是 CursorType 或 LockType 传了非法值。比如传了 5 或 -1。检查常量值是否在 0-3 和 1-4 范围内。另外如果传的是字符串1而不是数字1某些提供者也会报这个错。错误二RecordCount返回 -1不是 bug是游标类型不支持。默认的 AdOpenForwardOnly 就不支持计数。改成 AdOpenStatic3或 AdOpenKeyset1即可。注意 AdOpenDynamic 在某些提供者下也不支持 RecordCount。错误三当前记录集不支持更新LockType 是 1只读。改成 3乐观锁或 2保守锁。同时确认 Source 是单表查询多表 JOIN 的 Recordset 通常不可更新。错误四无法为更新定位行乐观锁下你打开记录到调用 Update 之间别人已经改了这条记录。ADO 找不到原始行。解决办法是重新查询后再改或者改用保守锁但要注意阻塞问题。错误五存储过程调用报「对象名无效」Options 没传或传错。存储过程要用 4AdCmdStoredProc表名用 2AdCmdTableSQL 语句用 1AdCmdText。不传时提供者会猜猜错就报错。错误六Arguments are of the wrong typeActiveConnection 传了一个已关闭的 Connection 对象。检查conn.State是否为 1adStateOpen关闭状态下传进去就会报这个。6. 把参数骨架用起来回到实际场景一个典型的分页列表页需要总记录数、需要翻页、只读。配置骨架就是rs.Open sql, conn, 3, 1静态游标加只读锁。一个编辑页需要定位单条记录并更新配置是rs.Open sql, conn, 1, 3键集游标加乐观锁。一个批量导入脚本配置是rs.Open sql, conn, 1, 4配合UpdateBatch使用。我试过在同一个页面里混用不同 CursorType 的 Recordset只要各自管理好连接互不影响。但要注意如果共用一个 Connection 对象前一个 Recordset 没关闭就打开下一个某些提供者会报「连接忙」。养成用完就rs.Close的习惯比事后排查省事得多。如果你在配 LockType 时拿不准该用乐观还是保守可以把你的并发场景描述给模型对话让它帮你分析冲突概率和阻塞风险 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel-chat 。需要批量处理老代码里的 Recordset.Open 调用、统一参数规范的话Coding Plan 更适合这种长期编码任务 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding-plan 。Key 在 API Keys 页面拿接入细节看文档 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi-keys 和 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc 。
返回列表