如何将代码从DAO重写为ADO?

Posted

技术标签:

【中文标题】如何将代码从DAO重写为ADO?【英文标题】:how to rewrite code from DAO to ADO? 【发布时间】:2017-05-14 23:40:44 【问题描述】:

我们有一些旧的遗留应用程序是在 2000 年开发的,我们已经从 2003 年访问到 2007 年。当我尝试运行应用程序的模块时,它给了我一个错误:

“运行时错误 3847。不再支持 ODBCDirect。重写代码以使用 ADO 而不是 DAO”。

它突出显示到Set WS = CreateWorkspace("NewWS", "", "", dbUseODBC) 行。由于我对 Access 非常陌生,因此我在此处发布此问题之前进行了研究,但没有运气。我正在尝试重写代码以使用 ADO 而不是 DAO。

以下是我的旧 vba 代码:

Public Function GetID (ByRef SegmentItem As clsSegmentDefinitions) As Long 
    Dim qdf As QueryDef
    Dim qdfNewID As QueryDef
    Dim rs As Recordset
    Dim rsNewID As Recordset
    Dim NaturalDescription As String
    Dim WS As Workspace
    Dim con As Connection 
    Set WS = CreateWorkspace("NewWS", "", "", dbUseODBC)
    WS.DefaultCursorDriver = dbUseODBCCursor
    Set con = WS.OpenConnection("", , , SQLConnectString)
    DoCmd.Hourglass False
    DoCmd.OpenForm " frmQuickAdd_AddNatural ", , , , , acDialog, SegmentItem.AddValue
    DoCmd.Hourglass True
    If Form_frmQuickAdd_AddNatural.Tag Then
        Set qdf = con.CreateQueryDef("", " ? = call sp_Insert(?, ?, ?) ")
        qdf.Parameters.Refresh
        qdf![@prmDescription] = Left(Form_frmQuickAdd_AddNatural.txtSegmentDescription, 34)
        qdf![@prmCreateUser] = CurrentUser
        qdf![@prmProjectID] = 0
        qdf.Execute
        Set qdfNewID = CodeDb.CreateQueryDef("")
        qdfNewID.Connect = SQLConnectString
        qdfNewID.ReturnsRecords = True
        qdfNewID.SQL = "sp_GetNewSegmentID"
        Set rsNewID = qdfNewID.OpenRecordset
        If Not IsNull(rsNewID!MaxOfSegmentID) Then
            GetID = rsNewID!MaxOfSegmentID
        Else
            GetID = 0
        End If        
    Else
        GetID = 0
    End If
    DoCmd.Close acForm, "frmQuickAdd_AddNatural"    
End Function

我已经开始重写代码,但我不知道它是否应该是这样的。

Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset

cnn.Open "Provider=mssql;Data Source=" & dbq & ";User Id=" & uid & ";Password=" & pwd
With rst
    .Open "SELECT COUNT(*) FROM " & tbl, cnn, adOpenKeyset, adLockOptimistic
    num = .Fields(0)
    .Close
End With
cnn.Close
Set rst = Nothing
Set cnn = Nothing

【问题讨论】:

改写成ADO会做很多工作。或者,修改 - 仍然使用 DAO - 以在没有 ODBC 工作区的情况下工作。 我会将整个内容移植到 SQL Server 免费版。我最近花时间在 Access 上仍然有很多错误。可怕。 我已重新格式化您的问题以修复代码块,但此时您的问题基本上过于宽泛。您可以在Documentation.SO 找到有关 ADO 的信息;一旦您遇到具体的问题,您就会有具体的问题,我们可以为您提供具体的答案。现在看起来你是在要求其他人为你做“翻译”工作,这不是 Stack Overflow 的目的。 @Mat'sMug:我将研究该文档。谢谢 @S Meaden: -- 用户已经在使用 SQL Server,并建议 SQL Server 不允许创建表单和 UI,这些表单和 UI 显然包含在给定的示例代码中。因此,除非您建议使用其他客户端开发工具,否则迁移到 SQL 并不能解决 UI 问题。 Access 是 Oracle 或在本例中是 SQL Server 的出色客户端。如前所述,用户已经在使用 SQL 服务器,并且存储过程名称在给定的示例代码中清晰可见。所以有问题的数据库引擎已经是 SQL 服务器。那么移植到 SQL Server 是如何允许构建表单和 UI 的呢? 【参考方案1】:

首先,您确实不想将 ADO 引入围绕 DAO 构建和设计的应用程序中。更糟糕的是,ADO 已经退出了大约 15 年。事实上,SQL Server 正在放弃对 ADO 工作的 oleDB 的支持。 (所以不要去那里)。

有关 SQL Server 放弃 oleDB 支持的信息,请参阅此链接:

http://blogs.msdn.com/b/sqlnativeclient/archive/2011/08/29/microsoft-is-aligning-with-odbc-for-native-relational-data-access.aspx

行业已远离 ADO,所有主要供应商都建议使用开放式数据库连接作为行业标准。 (这意味着 ODBC)。

我将在 Access 中创建并保存传递查询。然后您的代码可以重写为:

Public Function GetID(ByRef SegmentItem As String) As Long

  Dim strSQL     As String

  strSQL = "sp_Insert('" & _
           Left(Form_frmQuickAdd_AddNatural.txtSegmentDescription, 34) & "'," & _
           "'" & CurrentUser & "', 0)"

  With CurrentDb.QueryDefs("qryPass")
     .SQL = strSQL
     .ReturnsRecords = False
     .Execute
  End If

  With CurrentDb.QueryDefs("qryPass")
     .SQL = "sp_GetNewSegmentID"
     .ReturnsRecords = True
     GetID = Nz(.OpenRecordset()("MaxOfSegmentID"),0)
  End With

End Function

所以创建一个传递查询。您可以在使用 JET-DIRECT 的所有地方使用它。在 access 2007 中,jet-direct 支持被删除,但使用简单的 pass-through 查询就足够了,而且如上所示,可以节省大量的编码和开发人员时间。如果您拥有的“左”表达式可以返回 null,那么您可能需要将该表达式包装在 nz() 中以返回“”(空字符串)或适当的值。

【讨论】:

感谢您的回复。我正在研究在线传递查询。那么,上面的“qrypass”就是直通查询,对吧?传递查询里面有什么?是存储过程 sp_insert 吗? 您可以在传递查询中放置您想要的任何内容。因此,只需使用来自 tblCustomers 的简单选择计数 (*) 来测试 PT。 PT 查询可以从任何合法的 t-sql 语句开始。上面显示您将“经常”将该 PT 查询的 .SQL 文本属性修改为即时的任何内容。因此,首先通过单击它来运行它来测试 PT 查询一旦工作,然后上面的代码会根据上面的动态更改 .SQL 属性。这允许您在该 PT 查询中填充 + 使用任何 t-sql。这也意味着您不会在代码中弄乱连接字符串,并且可以很好地替换 jet-direct 代码。 上面 qryPass 中的任何 yes 都是我用于 PT 查询的名称 - 它可以是您想要的任何名称。这种方法是首选,因为您的 DAO 记录集代码的其余部分不必重新编写,并且可以像以前一样工作。因此,这种方法对现有 DAO 记录集代码的更改最少。 更新:blogs.msdn.microsoft.com/sqlnativeclient/2017/10/06/… 请注意,该代码似乎创建了一个独立于 Access 的单独 ODBCDirect 连接,这意味着 ADO 在这里确实有意义(或者至少它曾经如此)。

以上是关于如何将代码从DAO重写为ADO?的主要内容,如果未能解决你的问题,请参考以下文章

将 DAO 记录集转换为断开连接的 ADO 记录集 dbDecimal 问题

VB.NET 从 DataTable 对象将表附加到数据库

作为 SQL Server 的前端访问 - ADO 与 DAO?

如何将 DAO 查询转换为 Yii2 ActiveRecord。如何从连接表中选择和使用特定列

VB6 - DAO - 存储过程

ADO.net 如何将数据库单元格变成整数?