MS Access 表单绑定到 ADO 记录集

MS Access Form Bind to ADO Recordset

快把我逼疯了...

问题之一是速度。

我有一个正常工作的 SQL 服务器链接到一个客户可访问的网站,我想添加一个 Access 前端以使我们的办公室工作人员能够更好地支持客户和现场工作人员。

我目前构建的表格是一个主表格,其中包含五个子表格,在一个视图中为我们提供了所有相关的客户信息。然而,这有效需要 24 秒来加载单个客户端的完整记录。

我查看了 SQL 服务器,发现缺少索引,修复了这个问题,并将时间缩短到 24 秒,随后加载时间接近 18 秒,具体取决于客户端(有些有更多记录)。这可能没问题,因为虽然这是现实世界时间中计算时间的相对永恒,但没关系......但不是很好。我想看看我是否可以通过更改我的连接方式以及表单如何绑定到记录等来获得更好的负载

在查看各种想法并大量阅读时,我发现: https://docs.microsoft.com/en-us/office/vba/access/concepts/activex-data-objects/bind-a-form-to-an-ado-recordset?source=docs

这对我很有吸引力,因为我更倾向于使用 ADO,很少使用 DAO。我理解的 ADO 最初是为了与 SQL 等一起使用,这似乎是一个明智的想法。

再一次,据我所知,如果我能让它工作,它将充当传递查询,仅通过网络返回一条记录,因此应该大大加快我的表单。但是它不会工作。

我的代码是:

Private Sub cssSetForm(lngID As Long)
Dim cnn As New ADODB.Connection
Dim Rs1 As New ADODB.Recordset
Dim strSQL As String
Dim strR As String  

cnn = "Provider=MSOLEDBSQL;Server=Server;Database=DatabaseName;UID=UserName; PWD=Password;"   
cnn.Open

  strSQL = "SELECT Clients.Clientid, Clients.AccountContact, Clients.AccountEmail, Clients.Address, Clients.Name, Clients.OfficePhone, Clients.PostCode, " & _
           "Clients.ShentonAcc, Clients.Suburb FROM Clients WHERE (((Clients.Clientid)=" & lngID & "));"



    With Rs1

        Set .ActiveConnection = cnn
        .Source = strSQL
        .LockType = adLockPessimistic
        .CursorType = adOpenKeyset
        .Open

    End With


     Debug.Print Rs1.RecordCount

   Me.Recordset = Rs1

  End sub

现在我没有收到任何错误,直到 Me.Recordset=rs1 生成错误 3251 此类对象不支持操作,这对于理解为什么不支持它的人来说非常好与我从中复制的示例没有什么不同。

根据错误消息,我不明白为什么我正在处理的表单不支持记录集?我的代码有错误吗?我对链接站点的破坏的理解有误吗?是不是其他错误?

感谢帮助

好吧,加载 5 个子表单需要大量数据。转换为 ado reocdsets 不会加快速度。

您在这里要做的是在用户说单击相应的选项卡以加载给定的子表单之前不加载子表单。

只要有问题的表单是用 were 子句打开的,那么一个主表单只会从 sql 服务器中拉出一个主记录。所以做各种花哨的 reocrdsets 等会让你几乎一无所获。所以,总是 - 但总是将您的主窗体启动到一个记录。如果该主窗体绑定到 5,000 行或 100 万行的 table,它将立即加载,尽管该窗体直接绑定到 linked table with 1百万行。

使用这个主窗体,您可以编辑或执行任何操作,然后将其关闭。然后你当然会回到搜索 form/prompt 你必须询问用户要处理什么 reocrd。那么,会计包是如何工作的,甚至 google?您搜索、显示搜索结果并选择一件事情进行查看。这种方法应该使您的主窗体加载时间减少到大约 1 秒。同样,在打开该表单时只需使用 "where" 子句: 例如:

dim strInv   as string
strInv = InputBox("Enter invoice number to view")
docmd.OpenForm "frmInvoice",,,"InvoiceNum = " & strInv

当然上面是航空代码,你可能会建立一些搜索表单,比如这样:

所以在上面,用户输入了一些名字。然后我们用一个简单的 where 子句或

填写表格
me.MySubForm.RecordSource = "select * from tourCust where LastName like '" & sTextbox & "*'"

当用户点击眼镜图标编辑+查看一行时,我们使用这个:

docmd.OpenForm "frmDetails",,,"id = " & me!id

同样,所有绑定的表单,尽管 table 有 500,000 多行,表单的加载是即时的 - 即使后端是 SQL 服务器。

所以,采用提示+搜索结果+edit/view的设计模式。每个软件系统都有这种循环或设计模式。它不仅对用户友好,而且性能也很好,因为访问不会拉取整个 table,而只会拉取您告诉表单加载的 reocrds,按照上面的方法使用 where 子句。

现在,对于子表单(sub forms)。 如前所述,在用户实际单击给定选项卡之前不要加载它们。

所以,在tab的on-change事件中,你可以去:

If Me.TabMainpage.Pages(Me.TabMainpage).Name = Me.pgeDocs.Name Then

'' the tab been changed to show past tours
dim strSQL as string
strSQL = "select * from tblPastTours where tour_ID = " & me!ID
me.
' dynamic load the sub form
If Me.frmSubPastTours .SourceObject = "" Then
     Me.frmSubPastTours.SourceObject  = "Forms.frmPastTours"
End If
' now load sql into form
 me.frmSubPastTours.Form.RecordSource = strSQL

以上大部分是air代码,但这里的思路是:

除非需要,否则不要加载子表单。 或者您可以加载子表单,但将其 RecordSource 留空,并在单击选项卡时需要显示的 sql 中填充 STUFF。

您可能需要显示所有子表单。因此,您可以将所有子表单 RecordSource 留空,然后将其作为主表单加载事件,只需将 sql 填充到每个子表单即可。这可能会稍微提高速度,并且由于连接速度较慢,这将是最少的工作量。

你 "fail" 提及你如何启动 + 加载主窗体,但如前所述,它应该打开到 ONE reocrd。 link master/child 提取数据可能有点慢,我不能说仅将上述 sql 内容用于这些表格会有很大帮助。我会先尝试,因为这是最少的工作量。如果加载时间仍然太慢,那么将子表单放在选项卡控件后面,只加载子表单,然后设置数据源将是最快的。

试图构建所有这些记录集,然后将它们绑定到一个表单?它不会加快速度,只是将 sql 字符串推入表单(或子表单)recordSource 无论如何,实际上是相同的事情和相同的性能。所以,你节省了大量的工作和代码,而且上面的想法不仅适用于 sql 服务器后端,而且我们都非常经常动态加载子表单并且在你查看之前不加载它们子表单在选项卡控件后面说。