首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在VBA中使用KDB+/qodbc.dll的ADO

在VBA中使用KDB+/qodbc.dll的ADO
EN

Stack Overflow用户
提问于 2014-07-05 06:30:25
回答 1查看 1.2K关注 0票数 5

我有一个基于Excel的应用程序,它依赖于我使用ADO (Microsoft数据对象6.1Library)连接到的几个不同的数据库。数据库驻留在区域服务器上,建立初始连接存在开销,因此我将连接缓存在Scripting.Dictionary对象中以供重用。

代码语言:javascript
运行
AI代码解释
复制
Private moConnCacheDict As Scripting.Dictionary

当我使用kdb+ qodbc.dll数据库驱动程序时,我会得到意想不到的行为。我可以像预期的那样连接和重用多个数据源(Oracle、Sybase、Access)和一个KDB数据库实例。但是,如果创建第二个KDB数据库连接并在新数据集上执行查询,则尽管查询是合法的,也不会返回任何数据。

代码语言:javascript
运行
AI代码解释
复制
Recordset.BOF = TRUE and Recordset.EOF = TRUE 

它看起来执行得很好,而且字段是可见的。与前一个区域服务器的连接似乎持续存在,我可以成功地检索驻留在原始服务器上的数据,尽管如果我查看,

代码语言:javascript
运行
AI代码解释
复制
Recordset.ActiveCommand.ActiveConnection.Properties.Item("Extended Properties")

,是新的连接字符串。

KDB+连接字符串使用以下语法:

代码语言:javascript
运行
AI代码解释
复制
DRIVER=kdb+;DBQ=XXXXX;UID=XXXXX;PWD=XXXXX;

我已经包含了用作示例的核心VBA函数:

代码语言:javascript
运行
AI代码解释
复制
Private Function ExecuteQuery(sDBName As String, ByRef oRst As ADODB.Recordset, Optional bDeleteConnection As Boolean) As Boolean
Dim oDBConn As ADODB.Connection
Dim sSql As String

'delete connection
If bDeleteConnection Then Call DropConnection(sDBName)

'get cached or new connection
Call GetConnection(sDBName, oDBConn)

Select Case sDBName
Case "MAIN_US"
    sSql = mSQL_MAIN
Case "MD_ASIA"
    sSql = mSQL_MDASIA
End Select

Set oRst = New Recordset
oRst.Open sSql, oDBConn, adOpenKeyset, adLockPessimistic

If Not oDBConn.State = adStateOpen Then Err.Raise vbObjectError + 1024, "ExecuteQuery", sDBName & ": Recordset Closed. Unable to execute query ->" & sSql

ExecuteQuery = True

End Function

Private Function GetConnection(sDBName As String, ByRef oDBConn As ADODB.Connection) As Boolean

If moConnCacheDict Is Nothing Then Set moConnCacheDict = New Dictionary

If moConnCacheDict.Exists(sDBName) Then
'get existing connection
Set oDBConn = moConnCacheDict.Item(sDBName)
Else
'create connection
Set oDBConn = New Connection

With oDBConn
    .Mode = adModeRead
    Select Case sDBName
    Case "MAIN_US"
        .Mode = adModeReadWrite
        .ConnectionString = mCONN_MAIN
    Case "MD_ASIA"
        .Mode = adModeRead
        .ConnectionString = mCONN_MDASIA
    End Select

    .CursorLocation = adUseServer
    .Open
End With

moConnCacheDict.Add sDBName, oDBConn

End If

GetConnection = True

End Function

Private Function DropConnection(Optional sDBName As String) As Boolean
Dim oDBConn As ADODB.Connection
Dim i As Integer

    'delete object directly from cache
    If Not moConnCacheDict Is Nothing Then
        If sDBName = vbNullString Then
                'close all connections
                For i = 0 To moConnCacheDict.Count - 1
                    If Not IsEmpty(moConnCacheDict.Items(i)) Then
                        Set oDBConn = moConnCacheDict.Items(i)
                        If Not oDBConn Is Nothing Then
                            If oDBConn.State = adStateOpen Then oDBConn.Close
                            Set oDBConn = Nothing
                            Debug.Print Now, "Dropping Database Connection - " & moConnCacheDict.Keys(i)
                        End If
                    End If
                Next i
                Set moConnCacheDict = Nothing
            Else
            If moConnCacheDict.Exists(sDBName) Then
                If Not IsEmpty(moConnCacheDict.Item(sDBName)) Then
                    Set oDBConn = moConnCacheDict.Item(sDBName)
                    If Not oDBConn Is Nothing Then
                        If oDBConn.State = adStateOpen Then oDBConn.Close
                        Set oDBConn = Nothing
                        Debug.Print Now, "Dropping Database Connection - " & "Dropping Database Connection - " & sDBName
                    End If
                End If
                moConnCacheDict.Remove (sDBName)
            End If
        End If
    End If

DropConnection = True

End Function

(注意,调用方总是关闭ADO.Recordset并将其设置为空)。

解决此问题的唯一方法是关闭所有数据库连接(不管提供程序如何),然后重新连接到所需的区域服务器。这是可怕的低效,因为我必须重新打开所有现有的连接。还请注意,仅仅在当前工作簿中这样做是不够的。必须在应用程序级别完成。如果到任何数据库的任何ADO连接仍然处于打开状态,我可以创建一个新的KDB+ ADO连接,但它仍然指向上一个实例

我查看了KDB+连接对象的错误属性,有两个错误:

  1. 多步OLE DB操作生成错误。如果可用,请检查每个OLE DB状态值。没有做任何工作。
  2. 提供程序不支持该属性。

这似乎被记录在http://support.microsoft.com/kb/269495中,但我无法在注册表中找到任何CLSID,因此无法对建议的更改进行实验。

如果打开ODBC日志记录,我会看到以下消息:

代码语言:javascript
运行
AI代码解释
复制
EXCEL                   8dc-22d0    EXIT  SQLGetInfoW  with return code -1 (SQL_ERROR)
    HDBC                0x02131EA8
    UWORD                      151 <SQL_KEYSET_CURSOR_ATTRIBUTES2>
    PTR                 0x003C4FB0
    SWORD                        4 
    SWORD *             0x00000000

    DIAG [S1096] [Microsoft][ODBC Driver Manager] Information type out of range (0) 

这会对错误负责吗?

一如既往,任何帮助和建议都将不胜感激。

EN

回答 1

Stack Overflow用户

发布于 2014-10-08 08:16:16

您所看到的是驱动程序中的一个bug,您应该查找更多最新的驱动程序。

如果我没有亲自运行和测试代码,我不应该给出完整的答案(而不是注释),但是我建议您枚举连接对象的属性集合并查找连接池。

将连接池设置为0(或为false,取决于从查看属性值的变量类型中可以猜测到什么)是一种很有希望的解决方法。您的另一个选项是使用只转发的记录集:这可能有效,也可以不起作用,但值得一试。

注:几年前有一个开源项目,要编写一个适当的OLEDB驱动器,但这似乎已经从人们的视野中消失了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24587421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档