VB6 ADODB.Recordset RecordCount属性始终返回-1

时间:2010-02-17 16:57:03

标签: sql-server database vb6 ado adodb

我正在尝试使用一些旧的VB6代码来使用SQL Server Compact。

我可以连接,打开数据库,一切似乎都很好。我可以运行插入选择命令。

但是ADODB.Recordset RecordCount属性总是返回-1,即使我可以访问Fields并查看数据。更改CursorLocation = adUseClient会在执行SQL时产生问题(多步操作生成错误)。

Option Explicit
    Private Const mSqlProvider          As String = "Provider=Microsoft.SQLSERVER.CE.OLEDB.3.5;"
    Private Const mSqlHost              As String = "Data Source=C:\Database.sdf;"
    Private mCmd                        As ADODB.Command   ' For executing SQL
    Private mDbConnection               As ADODB.Connection


Private Sub Command1_Click()


   Dim rs As ADODB.Recordset

    Set rs = New ADODB.Recordset


    Dim DbConnectionString As String

    DbConnectionString = mSqlProvider & _
                            mSqlHost


    Set mDbConnection = New ADODB.Connection
    mDbConnection.CursorLocation = adUseServer

    Call mDbConnection.Open(DbConnectionString)

    If mDbConnection.State = adStateOpen Then
        Debug.Print (" Database is open")
        ' Initialise the command object
        Set mCmd = New ADODB.Command
        mCmd.ActiveConnection = mDbConnection

        mCmd.CommandText = "select * from myTestTable"
        mCmd.CommandType = adCmdText

        Set rs = mCmd.Execute

        Debug.Print rs.RecordCount  ' Always returns -1  !!
        Debug.Print rs.Fields(0)   ' returns correct data for first row, first col
        Debug.Print rs.Fields(1)   ' returns correct data for first row, 2nd col
        Debug.Print rs.Fields(2)   ' returns correct data for first row, 3rd col

    End If

End Sub

任何建议都会被感激地接受。

12 个答案:

答案 0 :(得分:5)

实际上CursorLocation在这种情况下起着重要作用。使用rs.CursorLocation = adUseClient设置光标位置并尝试。

    Set rs = New ADODB.Recordset
    rs.CursorLocation = adUseClient
    Dim DbConnectionString As String

    DbConnectionString = mSqlProvider & _
                            mSqlHost


    Set mDbConnection = New ADODB.Connection
    mDbConnection.CursorLocation = adUseServer

    Call mDbConnection.Open(DbConnectionString)

    If mDbConnection.State = adStateOpen Then
        Debug.Print (" Database is open")
        ' Initialise the command object
        Set mCmd = New ADODB.Command
        mCmd.ActiveConnection = mDbConnection

        mCmd.CommandText = "select * from myTestTable"
        mCmd.CommandType = adCmdText

        Set rs = mCmd.Execute

        Debug.Print rs.RecordCount  ' This should now return the right value.
        Debug.Print rs.Fields(0)   ' returns correct data for first row, first col
        Debug.Print rs.Fields(1)   ' returns correct data for first row, 2nd col
        Debug.Print rs.Fields(2)   ' returns correct data for first row, 3rd col

    End If

End Sub

答案 1 :(得分:3)

这是用于访问数据的游标类型的结果,这篇文章涵盖了问题和可能的修复。

http://www.devx.com/tips/Tip/14143

修改

我为没有更加关注您处理Compact的事实而道歉。使用Compact时,情况类似于我引用的情况,因为它默认使用仅向前游标(不支持行计数),但是有两种其他游标类型可用,如下面的链接所示。

http://support.microsoft.com/kb/272067

答案 2 :(得分:2)

检查记录集属性

以下是com.status.live代码

返回的RecordCount值的结果
+------------------+-------------------+-------------+---------------+--------------+
|    CursorTypeEnum|adOpenForwardOnly=0|dOpenKeyset=1|adOpenDynamic=2|adOpenStatic=3|
|CursorLocationEnum|                                                                |
+------------------+-------------------+-------------+---------------+--------------+
|adUseServer = 2   |         X         |      O      |       X       |       O      |
|adUseClient = 3   |         O         |      O      |       O       |       O      |
+------------------+-------------------+-------------+---------------+--------------+

答案 3 :(得分:2)

以下是我使用

的解决方案
Dim recordnumber As Long
Dim SalRSrec As New ADODB.Recordset
Set SalRSrec = Nothing
SalRSrec.Open ("SELECT count(*) from SALARY where EMPID= '" & cmb_empid & "' ;"), Dbase, adOpenKeyset, adLockOptimistic
recordnumber = SalRSrec.GetString
MsgBox recordnumber

答案 4 :(得分:1)

很久以前,在使用VB6 / ADO的内存中,.RecordCount字段在您移动到记录集的末尾之前不会返回有意义的数据。

rs.MoveLast
rs.MoveFirst
Debug.Print rs.RecordCount

虽然有了这个,你需要确保你有适当的光标类型(即,不仅仅是向前)。

我能想到的唯一其他解决方案是单独执行SELECT COUNT(*)FROM myTestTable等,但这会导致该调用与实际返回行之间数据发生变化的问题。

答案 5 :(得分:1)

使用Compact,默认光标属性为adOpenForwardOnly,以提高性能。因此,RecordCount返回为“-1”,这意味着它不可用,而不是空白。这是设计原因,因为动态游标中的记录数可以更改并导致在客户端服务器之间来回ping以保持准确性。但是,如果记录计数至关重要,请尝试将其设置为使用adOpenKeyset或adOpenStatic与服务器端游标。

答案 6 :(得分:1)

你可以尝试这样的事情......

Set rs = mCmd.Execute

rs.MoveFirst

Do Until rs.EOF = true

    Debug.Print rs.RecordCount  ' Always returns -1  !!
    Debug.Print rs.Fields(0)   ' returns correct data for first row, first col
    Debug.Print rs.Fields(1)   ' returns correct data for first row, 2nd col
    Debug.Print rs.Fields(2)   ' returns correct data for first row, 3rd col

   counter = counter + 1
   rs.MoveNext

Loop

答案 7 :(得分:0)

Set rs = mCmd.Execute替换为:

set rs = new ADODB.Recordset
rs.Open "select * from myTestTable", mDBConnection, adOpenDynamic, adLockOptimistic

adOpenDynamic将允许向前/向后阅读以获取您的记录数。

答案 8 :(得分:0)

下面的代码可能对您有帮助,

set conn = CreateObject("ADODB.Connection") 
conn.open "<connection string>" 
set rs = CreateObject("ADODB.Recordset") 
sql = "SELECT columns FROM table WHERE [...]" 
rs.open sql,conn,1,1 
if not rs.eof then 
    nr = rs.recordcount 
    response.write "There were " & nr & " matches." 
    ' ... process real results here ... 
else 
    response.write "No matches." 
end if 
rs.close: set rs = nothing 
conn.close: set conn = nothing 

答案 9 :(得分:0)

如果仍然返回-1

,请尝试使用以下代码
Set Conn = createobject("ADODB.connection")
Set Rs = createobject("ADODB.recordset")
Conn.Open "DSN=DSN_QTP" 
'Rs.Open "Select * From orders",Conn,adOpenDynamic,adLockBatchOptimistic
Rs.Open "Select * from [QTP-Table]",Conn,1 'Use either 1 or 3
'I tried using adopendynamic but it still returned -1. Using 1 it gave me correct count.       'Though I am using this code in QTP (Vbscript) same should work for VB6 also.
msgbox Rs.RecordCount

答案 10 :(得分:0)

Set cn = CreateObject("ADODB.Connection")

strVerb = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
    "Data Source=C:\test.accdb"

tab1 = "tabelle1"

strSQL = "SELECT Count(*) FROM " & tab1

Debug.Print strSQL
         
cn.Open strVerb
Set rs = cn.Execute(strSQL)

Debug.Print rs.Fields(0)
    
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing

答案 11 :(得分:-1)

以下代码完全返回recortcount ...

Public Sub test()
    Dim cn As New ADODB.Connection()
    Dim sPath As String = Application.ExecutablePath
    sPath = System.IO.Path.GetDirectoryName(sPath)

    If sPath.EndsWith("\bin") Then
        sPath = sPath.Substring(0, Len(sPath) - 4)
    End If

    Dim DbConnectionString As String
    DbConnectionString = "provider=microsoft.jet.oledb.4.0;data source=" & sPath & "\students.mdb"

    cn.ConnectionString = DbConnectionString
    cn.Open()

    Dim rs As New ADODB.Recordset()
    rs.CursorLocation = ADODB.CursorLocationEnum.adUseClient
    rs.CursorType = ADODB.CursorTypeEnum.adOpenStatic
    rs.LockType = ADODB.LockTypeEnum.adLockBatchOptimistic
    rs.Open("select * from students", cn)
    MsgBox(rs.RecordCount)

    rs.ActiveConnection = Nothing
    cn.Close()
End Sub