2010-02-17 35 views
7

Próbuję uzyskać stary kod VB6 do pracy z SQL Server Compact.VB6 ADODB.Recordset Właściwość RecordCount zawsze zwraca -1

Mogę się połączyć, otworzyć bazę danych i wszystko wygląda dobrze. Mogę uruchamiać polecenia wyboru insertów, które działają.

Jednak właściwość RecordCount ADODB.Recordset zawsze zwraca -1, mimo że mogę uzyskać dostęp do pól i zobaczyć dane. Zmiana CursorLocation = adUseClient powoduje problem podczas wykonywania SQL (błędy generowane przez operacje wieloetapowe).

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 

Wszelkie porady będą z wdzięcznością przyjęte.

Odpowiedz

3

Jest to wynikiem rodzaju kursora używanego do uzyskania dostępu do danych, ten post obejmuje problem i możliwe poprawki.

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

EDIT

Przepraszam za nie bycie bardziej zwracać uwagę na fakt, że mieli do czynienia z Compact. W przypadku Compact sytuacja jest podobna do tej, do której się odwoływałem, ponieważ używa domyślnie kursorów tylko do przodu (które nie obsługują liczby wierszy), ale istnieją dwa inne typy kursorów, jak udokumentowano w poniższym łączu.

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

+0

wypróbowano obie metody i nie udało się wykonać "wybierz * z myTestTable ". Nawiasem mówiąc, jeśli otworzę sdf przez Sql Server Management Studio 2008 sql działa i zwraca 11 wierszy. – Belliez

0

Wymień Set rs = mCmd.Execute z:

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

adOpenDynamic pozwoli przodu/do tyłu przeczytać, aby uzyskać recordcount.

+0

Próbowałem tego, ale wystąpił błąd, gdy uruchomię polecenie rs.open: "Wystąpiły błędy. [,,,,,,]" – Belliez

+1

@Belliez: Czy możesz być bardziej konkretny? Jaki błąd wystąpił? –

+0

wystąpił błąd, o którym wspomniałem w swoim komentarzu. Kiedy przekroczyłem rs.open, powiedział "Wystąpiły błędy. [,,,,,,]", który nie jest zbyt szczegółowy !!!! – Belliez

3

W rzeczywistości w tym przypadku główną rolę odgrywa CursorLocation. Użyj rs.CursorLocation = adUseClient, aby ustawić położenie kursora i spróbuj.

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 
+0

Próbowałem tego i nadal zwraca -1 – Belliez

+0

Chociaż CursorLocation napędza zachowanie, to jest równie zależne od sterownika, którego używasz. Właściwie rs.CursorLocation = adUseClient umożliwia użycie kursorów sterownika. Zapoznaj się z dokumentacją używanego sterownika (Microsoft.SQLSERVER.CE.OLEDB.3.5), aby uzyskać informacje o funkcjach kursora. Sterownik CE może tego nie zapewniać. W takim przypadku możesz poszukać zaktualizowanego sterownika. – Kangkan

+0

Czy można również ustawić właściwość CursorLocation obiektu połączenia? – Kangkan

0

Z pamięci z pracy z VB6/ADO dawno pole .RecordCount nie zwraca znaczących danych, dopóki nie przeniósł się do końca rekordów.

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

Mimo to musisz się upewnić, że masz odpowiedni typ kursora (tzn. Nie przesyłaj dalej).

Jedyne inne rozwiązanie, jakie mogę wymyślić, to wykonanie oddzielnego SELECT COUNT (*) z myTestTable, itp., Ale ma to problemy z danymi zmieniającymi się między tymi wywołaniami, a tymi, które faktycznie zwracają wiersze.

1

Przy użyciu formatu Compact domyślnym atrybutem kursora jest adOpenForwardOnly, co zwiększa wydajność. Jako taki RecordCount jest zwracany jako "-1", co oznacza, że ​​jest on niedostępny, a nie pusty. Jest to zgodne z projektem, ponieważ liczba rekordów w dynamicznym kursorze może się zmienić i spowodować pingowanie tam iz powrotem między serwerem klienta, aby zachować dokładność. Jeśli jednak liczy się rekord, spróbuj ustawić go tak, aby korzystał z adOpenKeyset lub adOpenStatic z kursorem po stronie serwera.

-1

Ten kod zwraca dokładnie liczbę ponownych ...

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 
+0

wykorzystuje to bazę danych Access, a nie bazę danych SDF. – Belliez

1

poniższy kod może pomóc,

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 
2

Sprawdź rekordów Property

Kontynuacja to spowodować, że wartość RecordCount powrócił kodem 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

Oto rozwiązanie dla Ciebie, że użyłem

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 
0

Spróbuj użyć następującego kodu, jeśli nadal zwraca -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 
2

Możesz spróbować coś takiego ..

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