我正在对 Microsoft Access 2010 中的链接表应用程序进行一些维护工作,并遇到了这个小问题。该应用程序链接到 SQL Server 2008 数据库。该应用程序有一个主表单,允许用户选择公园代码和资源的组合,并弹出一个编辑表单以获取该特定组合的详细信息。如果数据库中不存在该组合,则应用程序会插入一条新记录,但问题是插入了 2 条记录。
这是问题代码的位置,当我需要在详细信息弹出表单中插入新记录时会调用它:
Private Sub New_Rec(unit_code As String, resource As String, sql As String)
DoCmd.RunSQL ("INSERT INTO PARK_RESOURCES (unit_code, resource, sensitivity) VALUES " _
& "('" & unit_code & "','" & resource & "','public')")
'Force an explicit save
'http://www.pcreview.co.uk/forums/update-cancelupdate-without-addnew-edit-t1150554.html
If Me.Dirty Then
Me.Dirty = False
End If
Me.RecordSource = sql
End Sub
创建“新”记录会导致 2 条记录插入到 Recordset 中。在设置 RecordSource 之前或之后移动显式保存代码似乎并不重要。以任一顺序(并在任一顺序后停止)都会在数据库中插入 2 条新记录(通过在 SSMS 中查询来验证)。
当我设置 RecordSource 属性并逐步执行代码时,事件链看起来像:Me.RecordSource = sql --> Form_BeforeUpdate() --> Form_AfterUpdate() --> Form_After_Insert() --> Form_Current()。在更新前结束时不存在副本,但是当我到达更新后时,副本已经被插入。BeforeUpdate 和 AfterUpdate 之间会发生什么导致这种情况发生?
根据MSDN,顺序是:BeforeInsert → BeforeUpdate → AfterUpdate → AfterInsert。他们还声明通过 Visual Basic 设置控件的值不会触发这些事件。但是当我在代码中更新 RecordSource 时,最后 3 个事件肯定会触发;BeforeInsert 是唯一一个不会停止单步执行的方法。
根据 Daniel Cook 的要求,这里是调用代码。
Private Sub Form_Load()
On Error GoTo Err_Form_Load
Me.KeyPreview = True
If Not IsNull(Me.OpenArgs) Then
ProcessOpenArgs (Me.OpenArgs)
Me.lblHeader.Caption = Me.unit_code & ": Resource - " & Me.resource
Else
Me.lblHeader.Caption = "Information Needs"
End If
... (error trapping)
End Sub
和 ProcessOpenArgs 子(OpenArgs 设置为“公园;资源”):
Private Sub ProcessOpenArgs(open_args As String)
On Error GoTo Err_ProcessOpenArgs
Dim Args() As String
Args = Split(open_args, ";")
Me.unit_code = Args(0)
Me.resource = Args(1)
'Check to see if there are records in the database for current unit/resource combo'
Dim rs As DAO.Recordset
Dim sql As String
sql = "SELECT * FROM PARK_RESOURCES " & _
"WHERE resource='" & Me.resource & "' AND unit_code='" & Me.unit_code & "'"
Set rs = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dbSeeChanges)
'if there aren''t, create a new record'
If (rs.RecordCount = 0) Then
New_Rec Me.unit_code, Me.resource, sql
Else 'go to the current listing'
Me.RecordSource = sql
End If
Exit_ProcessOpenArgs:
Exit Sub
Err_ProcessOpenArgs:
MsgBox Err.Number & Err.description
Resume Exit_ProcessOpenArgs
End Sub
我将继续梳理事件文档,作为最后的手段,我可能会完全发疯,只是将所有可能的事件粘贴到我的 VBA 代码中并逐步执行它们,但有谁知道可能发生什么导致重复?