Access链接SQL Server解决写入冲突时触发VBA运行时错误91求助
错误根因
- 你使用的OnActivate事件修复方案仅适用于绑定了记录源的窗体,你的主窗体控件均为未绑定控件,不存在绑定记录集,
Me.Recordset本身就是空对象,调用Clone方法自然触发运行时错误91。
解决方案
第一步:修复运行时错误91
直接删除以下两段完全不匹配你场景的事件代码即可:
Private Sub Form_Activate() Dim rs As ADODB.Recordset Set rs = Me.Recordset.Clone rs.Open rs.Bookmark = Me.Bookmark DoCmd.RunCommand acCmdRefresh Me.Bookmark = rs.Bookmark rs.Close Set rs = Nothing End Sub Private Sub Form_Deactivate() DoCmd.RunCommand acCmdSaveRecord End Sub
第二步:修复原有写入冲突问题
你之前触发写入冲突的核心原因是:直接修改子窗体绑定控件的值+链接SQL Server表的并发检查机制默认对比所有字段,同时未绑定主窗体的Me.Dirty = False操作属于无效操作,还可能触发意外的保存逻辑。
调整后的赋值逻辑代码如下(用批量更新子窗体记录集的方式替代直接给控件赋值,避免脏数据冲突):
Private Sub Observer_AfterUpdate() ' 先保存子窗体现有未保存修改 If Me.frmLPIDetail.Form.Dirty Then Me.frmLPIDetail.Form.Dirty = False End If ' 批量更新子窗体所有记录的观察者字段 Dim rs As DAO.Recordset Set rs = Me.frmLPIDetail.Form.RecordsetClone If Not rs.EOF Then rs.MoveFirst Do While Not rs.EOF rs.Edit rs!Data_observer = Me.Observer rs.Update rs.MoveNext Loop End If rs.Close Set rs = Nothing ' 刷新子窗体显示 Me.frmLPIDetail.Form.Requery End Sub Private Sub Recorder_AfterUpdate() ' 先保存子窗体现有未保存修改 If Me.frmLPIDetail.Form.Dirty Then Me.frmLPIDetail.Form.Dirty = False End If ' 批量更新子窗体所有记录的记录员字段 Dim rs As DAO.Recordset Set rs = Me.frmLPIDetail.Form.RecordsetClone If Not rs.EOF Then rs.MoveFirst Do While Not rs.EOF rs.Edit rs!Data_recorder = Me.Recorder rs.Update rs.MoveNext Loop End If rs.Close Set rs = Nothing ' 刷新子窗体显示 Me.frmLPIDetail.Form.Requery End Sub
优化建议(进一步降低写入冲突概率)
- 给SQL Server中对应的植被记录数据表添加一个
rowversion类型的字段,该字段无需手动维护,SQL Server会在记录变更时自动更新。Access刷新链接表后会自动识别该字段,仅用主键+rowversion字段做并发检查,无需对比所有字段,可大幅降低写入冲突概率 - Transect_OID字段的赋值也可以参照上面的批量更新逻辑实现
- 未绑定主窗体不要调用
Me.Dirty属性,该属性仅对绑定窗体生效
内容的提问来源于stack exchange,提问作者Sean McKenzie
相关产品推荐
相关产品推荐

