我正在对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时,已经插入了副本。 BeforeUpdate和AfterUpdate之间会发生什么导致这种情况发生?
根据MSDN, the order is: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设置为“park; resource”):
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代码中粘贴每一个可能的事件并逐步完成它们,但有没有人知道可能发生什么导致重复?
答案 0 :(得分:1)
在ProcessOpenArgs
中,If (rs.RecordCount = 0) Then
行可能会出现问题,除非您先使用rs.MoveLast
- 请参阅here
答案 1 :(得分:1)
当我在此设置Me.unit_code
和Me.unit
时:
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)
代码创建1条记录,然后New_Rec
在DB中插入第二条记录。当表单在Me.RecordSource = sql
之后自动重新查询时,它会粘贴第一条记录(由ProcessOpenArgs
中的Me.xxx = yyyy语句创建到DB中,然后将两者都拉回到表单记录集。这就是双插件来自。
为了纠正错误,我将Me.unit_code
和Me.resource
更改为本地子例程变量l_unit_code
和l_resource
,并将其用于ProcessOpenArgs
。这就解决了这个问题以及我对记录形成的第二个问题,即一种资源类型流入其他资源类型。
谢谢大家的帮助!