使用VBA更新Form的RecordSource时,在链接表中插入重复的行

时间:2012-12-13 20:42:32

标签: sql-server vba ms-access-2010

我正在对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代码中粘贴每一个可能的事件并逐步完成它们,但有没有人知道可能发生什么导致重复?

2 个答案:

答案 0 :(得分:1)

ProcessOpenArgs中,If (rs.RecordCount = 0) Then行可能会出现问题,除非您先使用rs.MoveLast - 请参阅here

答案 1 :(得分:1)

当我在此设置Me.unit_codeMe.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_codeMe.resource更改为本地子例程变量l_unit_codel_resource,并将其用于ProcessOpenArgs。这就解决了这个问题以及我对记录形成的第二个问题,即一种资源类型流入其他资源类型。

谢谢大家的帮助!