3

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 によると、順序は、 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コードにすべての可能なイベントを貼り付けてステップスルーするかもしれません.

4

2 に答える 2

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 に 2 番目のレコードを挿入します。フォームが の後に自動的に再クエリを実行するMe.RecordSource = sqlと、最初のレコード (Me.xxx = yyyy ステートメントによって作成されたもの)ProcessOpenArgsが DB に貼り付けられ、両方がフォーム レコードセットに引き戻されます。ここから二重挿入が行われます。

それを修正するために、Me.unit_codeMe.resourceをローカル サブルーチン変数l_unit_codeに変更し、l_resourceで代わりに使用しましたProcessOpenArgs。これにより、この問題だけでなく、あるリソース タイプから別のリソース タイプに流れ込むレコードで発生した 2 つ目の問題も解決されました。

助けてくれてありがとう!

于 2012-12-18T01:10:17.133 に答える
1

では、最初に使用しない限りProcessOpenArgs、行が問題になる可能性があります-こちらを参照してくださいIf (rs.RecordCount = 0) Thenrs.MoveLast

于 2012-12-15T23:42:53.167 に答える