VB6 ADODB.Recordset Свойство RecordCount всегда возвращает -1 - PullRequest
9 голосов
/ 17 февраля 2010

Я пытаюсь заставить старый код VB6 работать с SQL Server Compact.

Я могу подключиться, открыть базу данных и все, кажется, хорошо.Я могу запустить команды вставки выбора, которые работают.

Однако свойство ADODB.Recordset RecordCount всегда возвращает -1, хотя я могу получить доступ к полям и просмотреть данные.Изменение 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

Любой совет будет с благодарностью принят.

Ответы [ 11 ]

5 голосов
/ 18 февраля 2010

На самом деле 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
3 голосов
/ 17 февраля 2010

Это результат типа курсора, используемого для доступа к данным, этот пост посвящен проблеме и возможным исправлениям.

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

EDIT

Я прошу прощения за то, что не был более внимательным к тому факту, что вы имели дело с Компактом. С Compact ситуация аналогична той, на которую я ссылался, поскольку по умолчанию используются только курсоры вперед (которые не поддерживают счетчик строк), но есть два других доступных типа курсора, как описано в ссылке ниже.

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

2 голосов
/ 15 декабря 2012

Вот решение для вас, которое я использовал

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
2 голосов
/ 20 ноября 2012

Проверить свойство Recordset

Следствием является то, что значение RecordCount возвращается кодом com.status.live

+------------------+-------------------+-------------+---------------+--------------+
|    CursorTypeEnum|adOpenForwardOnly=0|dOpenKeyset=1|adOpenDynamic=2|adOpenStatic=3|
|CursorLocationEnum|                                                                |
+------------------+-------------------+-------------+---------------+--------------+
|adUseServer = 2   |         X         |      O      |       X       |       O      |
|adUseClient = 3   |         O         |      O      |       O       |       O      |
+------------------+-------------------+-------------+---------------+--------------+
1 голос
/ 20 декабря 2013

Вы можете попробовать что-то вроде этого ..

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
1 голос
/ 19 февраля 2010

С компактным атрибутом курсора по умолчанию является adOpenForwardOnly для повышения производительности. Таким образом, RecordCount возвращается как «-1», что означает, что он недоступен, а не пустой. Это сделано из-за того, что количество записей в динамическом курсоре может измениться и привести к пингу между клиентским сервером и обратно для поддержания точности. Однако, если количество записей является жизненно важным, попробуйте настроить его на использование adOpenKeyset или adOpenStatic с серверным курсором.

1 голос
/ 18 февраля 2010

Из памяти при работе с VB6 / ADO давным-давно поле .RecordCount не возвращает значимых данных, пока вы не перешли в конец набора записей.

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

Хотя при этом вам необходимо убедиться, что у вас есть соответствующий тип курсора (то есть, не только вперед).

Единственное другое решение, которое я могу придумать, - это сделать отдельную команду SELECT COUNT (*) FROM myTestTable и т. Д., Но это имеет проблемы с изменением данных между этим вызовом и тем, который фактически возвращает строки.

0 голосов
/ 15 декабря 2013

Попробуйте использовать следующий код, если по-прежнему возвращает -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
0 голосов
/ 14 февраля 2011

Ниже код может помочь вам,

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 
0 голосов
/ 23 февраля 2010

Этот следующий код возвращает счет пересчета точно ...

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
...