访问表单链接到断开连接的ADODB.Recordset:保存更改

时间:2014-12-16 11:51:21

标签: vba ms-access-2010 adodb

我正在尝试设置一个表单,以使用断开连接的ADODB.Recordset作为其来源 我遇到的问题是,在关闭表单并向提示回复“是”时,更改保存到原始Access表中。我错过了什么?

注意:请不要告诉我这个方法没用,它只是一个带有本地表的POC,我打算稍后尝试使用更“遥远”的记录集。

Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset

Private Sub Form_Load()
    Set conn = New ADODB.Connection
    conn.Open CurrentProject.Connection

    Set rs = New ADODB.Recordset
    With rs
        rs.CursorLocation = adUseClient
        rs.Open "select * from amsPor", conn, adOpenStatic, adLockBatchOptimistic
        Set rs.ActiveConnection = Nothing
    End With
    Set Me.Recordset = rs
    conn.Close
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Select Case MsgBox("Save changes ?", vbQuestion + vbYesNoCancel)
    Case vbNo
        'do nothing
    Case vbYes
        conn.Open CurrentProject.Connection
        rs.ActiveConnection = conn
        rs.UpdateBatch
        rs.Close
        conn.Close
        Set conn = Nothing
    Case vbCancel
        Cancel = True
    End Select
End Sub

重现步骤:

  • 拿一张有主键的小桌子
  • 使用它生成自动表单
  • 保存表单。
  • 将上述代码添加到表单中,替换select子句中的表名。
  • 清空表单的Record Source属性。
  • 保存并关闭表单。
  • 您可以打开表单并对数据进行更改。关闭后,系统将提示您保存更改。

编辑:我想知道问题是否可能出现在CurrentProject.Connection? 在调试窗口中,我输入? CurrentProject.Connection并获得以下内容:

Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source=\\xxxxxx\yyyy$\Documents\AMS.accdb;Mode=Share Deny None;Extended Properties="";Jet OLEDB:System database=C:\Users\G828992\AppData\Roaming\Microsoft\Access\System.mdw;Jet OLEDB:Registry Path=Software\Microsoft\Office\14.0\Access\Access Connectivity Engine;Jet OLEDB:Database Password="";Jet OLEDB:Engine Type=6;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password="";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=True;Jet OLEDB:Bypass UserInfo Validation=False

4 个答案:

答案 0 :(得分:1)

我来到这里寻找与你相同的答案,经过大量的谷歌搜索和反复试验,我终于能够完成你正在尝试做的事情。我知道这是一个老帖子,但我没有看到任何答案,实际上提供了一个答案,允许你试图做的工作。我将使用您的示例并尝试应用我必须更改的内容并添加以使其正常工作。

Dim rs As ADODB.Recordset
Dim conn As ADODB.Connection

Private Sub Form_Load()
    If CurrentProject.Connection.State = adStateOpen Then CurrentProject.Connection.Close

    Set conn = New ADODB.Connection
    conn.Open CurrentProject.Connection.ConnectionString

    Set rs = New ADODB.Recordset
    rs.CursorLocation = adUseClient
    rs.Open "select * from amsPor", conn, adOpenForwardOnly, adLockBatchOptimistic

    If Not rs Is Nothing Then
        If Not rs.ActiveConnection Is Nothing Then Set rs.ActiveConnection = Nothing
        If Not (rs.eof And rs.BOF) Then
            Set Me.Recordset = rs
        End If

        If conn.State = adStateOpen Then
            conn.Close
        End If
    End If

    Call AddNewRecord(Me.Recordset)
End Sub


Private Sub AddNewRecord(ByRef rs As ADODB.Recordset)
    On Error Resume Next 

    If Not rs Is Nothing Then
        If rs.Supports(adAddNew) Then
            rs.AddNew
            rs.Fields("FirstName").Value = "John"
            rs.Fields("LastName").Value = "Doe"

            If rs.Supports(adUpdate) Then rs.Update
        End If
    End If

    If Err.Number <> 0 Then
        Debug.Print "AddNewRecord Err Msg: " & Err.Description
        Err.Clear
    End If
End Sub


Private Sub Form_Unload(Cancel As Integer)
    Select Case MsgBox("Save changes ?", vbQuestion + vbYesNoCancel)
    Case vbYes
        Call UpdateDbWithRS(Me.Recordset)
    Case vbCancel
        Cancel = True
    Case Else
        ' Nothing.
    End Select
End Sub


Private Sub UpdateDbWithRS(ByRef rs As ADODB.Recordset)
    If Not rs Is Nothing Then
        If CurrentProject.Connection.State = adStateOpen Then CurrentProject.Connection.Close

        Set conn = New ADODB.Connection
        conn.Open CurrentProject.Connection.ConnectionString
        rs.ActiveConnection = conn

        If rs.Supports(adUpdateBatch) Then
            rs.UpdateBatch

            If Not conn Is Nothing Then
                If conn.State = adStateOpen Then conn.Close
                Set conn = Nothing
            End If
            If Not rs Is Nothing Then
                If rs.State = adStateOpen Then rs.Close
                Set rs = Nothing
            End If
        End If
    End If
End Sub

通过上面的代码,我能够添加 记录到我的记录集,并验证它没有显示在我的数据库表中。然后,当我执行 UpdateDbWithRS 时,我已添加到 Recordset 记录,之前已被推送到我的数据库表。

我对代码所做的最大改变是将conn.Open CurrentProject.Connection更改为conn.Open CurrentProject.Connection.ConnectionString,添加代码If CurrentProject.Connection.State = adStateOpen Then CurrentProject.Connection.Close以修复我收到的有关已经打开的连接的错误。然后我做的最后一个最大的改变是将adOpenStatic CursorType 替换为adOpenForwardOnly。我不确定最后一次更改是否真的需要,但我根据我在此Microsoft Support Site上找到的断开连接的RecordSet示例使用它。

答案 1 :(得分:0)

使用断开连接的记录集时,您无法获得自动更新表更改的好处。您需要实际运行SQL Update和插入语句来保存数据。

答案 2 :(得分:0)

首先,您的代码看起来很完美,也应该有效,但是......

解决方案1 ​​

根据我的经验,我建议忘记这些功能。几年前,我一直在努力解决同样的问题。我没有找到任何解决方案,但我几乎可以肯定多用户环境中使用的访问数据库无法更新,因为当其他用户同时进行更改时,Jet / ACE引擎不允许更新静态记录集(变更被拒绝)。

我使用&#34;临时表&#34;解决了这个问题。与形式结合:

DELETE * FROM ~TableName;
INSERT INTO ~TableName SELECT * FROM TableName;

用户可以编辑记录,直到打开表格。在 Form_Unload 事件中,我运行如下查询:

UPDATE t1 SET Field1 = t2.Field1,
Field1 = t2.Field2 ... and so on
FROM TableName As t1 INNER JOIN ~TableName AS t2 ON t1.Key = t2.Key

请注意,记录的插入和删除(如果允许)应单独处理。

<强>溶液2

使用动态游标并且不会将记录集与数据库断开连接;) 使用Form.Dirty property抓住更改。

答案 3 :(得分:-4)

您的所有代码均与DISCONNECTED RECORDSETS无关。您的记录集已连接。断开连接的记录集可以作为xml或二进制文件保存到文件中。没有底层数据库。

注意我们制作断开连接的记录集。

Sub Randomise
    Randomize 
    Set rs = CreateObject("ADODB.Recordset")
    With rs
        .Fields.Append "RandomNumber", 4 

        .Fields.Append "Txt", 201, 5000 
        .Open
        Do Until Inp.AtEndOfStream
            .AddNew
            .Fields("RandomNumber").value = Rnd() * 10000
            .Fields("Txt").value = Inp.readline
            .UpDate
        Loop
        .Sort = "RandomNumber"
        Do While not .EOF
            Outp.writeline .Fields("Txt").Value

            .MoveNext
        Loop
    End With
End Sub

以下是州

  

ConnectionState

     

ConnectionState枚举用于标识连接器空间对象的状态。 CSEntry.ConnectionState属性包含此枚举的值之一。

     

已连接

     

连接器空间对象连接到metaverse对象。

     

明确连接

     

连接器空间对象由MIISAdmins或MIISOperators组的成员由帐户连接器显式连接到元节对象。

     

断开连接

     

连接器空间对象未连接到元节对象,但可能是将来连接到元节对象的候选对象。

     

DisconnectedByFilter

     

连接器空间对象已被连接器过滤器规则断开。

     

明确断开连接   连接器空间对象未连接到元节对象,并且将来不会成为连接到元节对象的候选对象。   占位符连接器空间对象隐式存在于连接目录中,但尚未导入。