ADO与VBA中的KDB + / qodbc.dll

我有一个基于Excel的应用程序依赖于我使用ADO(Microsoft ActiveX数据对象6.1库)连接到几个不同的数据库。 数据库驻留在区域服务器上,并且在build立初始连接时有开销,所以我将连接caching在一个Scripting.Dictionary对象中以供重用。

Private moConnCacheDict As Scripting.Dictionary 

当我使用kdb + qodbc.dll数据库驱动程序时,我意想不到的行为。 我可以按预期方式连接和重用多个数据源(Oracle,Sybase,Access)和一个KDB数据库实例。 但是,如果创build第二个KDB数据库连接并对新数据集执行查询,则不pipe数据是合法的,都不返回数据。

 Recordset.BOF = TRUE and Recordset.EOF = TRUE 

它似乎执行良好,领域是可见的。 与以前的区域服务器的连接似乎仍然存在,我可以成功检索驻留在原始服务器上的数据,尽pipe事实上如果我看一下,

 Recordset.ActiveCommand.ActiveConnection.Properties.Item("Extended Properties") 

,是新的连接string。

KDB +连接string使用以下语法:

 DRIVER=kdb+;DBQ=XXXXX;UID=XXXXX;PWD=XXXXX; 

我已经包括了核心的VBAfunction作为例子:

 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总是closures,调用者设置为空)。

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

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

  1. 多步OLE DB操作产生的错误。 检查每个OLE DB状态值(如果可用)。 没有工作完成。
  2. 提供程序不支持该属性。

这似乎是http://support.microsoft.com/kb/269495中logging,但我无法findregistry中的任何CLSID,所以我无法尝试build议的更改。

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

 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) 

这是否会对错误负责?

一如往常,任何帮助和build议将不胜感激。

你看到的是驱动程序中的错误,你应该寻找更多的驱动程序。

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

将连接池设置为0(或者取决于您通过查看属性值的vartype可以猜到什么)是一个很有希望的解决方法。 你的另一种select是使用只能转发的logging集:可能或不可行,但值得尝试。

注意:几年前有一个开源项目可以写出一个合适的OLEDB驱动器,但是这似乎已经从视图中消失了。