2010-02-17 139 views
7

Tôi đang cố gắng để có được một số mã VB6 cũ để làm việc với SQL Server Compact.VB6 ADODB.Recordset RecordCount tài sản luôn luôn trả về -1

Tôi có thể kết nối, mở cơ sở dữ liệu và tất cả đều có vẻ tốt. Tôi có thể chạy chèn lệnh chọn mà làm việc.

Tuy nhiên thuộc tính ADODB.Recordset RecordCount luôn trả về -1 mặc dù tôi có thể truy cập Trường và xem dữ liệu. Thay đổi CursorLocation = adUseClient gây ra một vấn đề khi thi hành SQL (các lỗi được tạo ra trong nhiều bước).

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 

Bất kỳ lời khuyên nào cũng sẽ được chấp nhận một cách biết ơn.

Trả lời

3

Đó là kết quả của loại con trỏ được sử dụng để truy cập dữ liệu, bài đăng này đề cập đến vấn đề và các bản sửa lỗi có thể có.

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

EDIT

Tôi xin lỗi vì không được chú ý nhiều hơn đến thực tế là bạn đang đối phó với nhỏ gọn. Với Compact tình hình tương tự như tôi đã tham chiếu, vì nó chỉ sử dụng con trỏ phía trước theo mặc định (không hỗ trợ số hàng) nhưng có hai loại con trỏ khác có sẵn như được ghi trong liên kết bên dưới.

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

+0

đã thử cả hai phương pháp và cả hai đều không thực thi được "chọn * từ myTestTable ". Ngẫu nhiên, nếu tôi mở sdf thông qua Sql Server Management Studio 2008 sql hoạt động và trả về 11 hàng. – Belliez

0

Thay Set rs = mCmd.Execute với:

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

Các adOpenDynamic sẽ cho phép một forward/backward đọc qua để có được RecordCount của bạn.

+0

Tôi đã thử cách này nhưng gặp lỗi khi chạy rs.open: "Đã xảy ra lỗi. [,,,,,,]" – Belliez

+1

@Belliez: Bạn có thể cụ thể hơn không? Lỗi nào đã xảy ra? –

+0

lỗi xảy ra là lỗi tôi đã đề cập trong nhận xét của mình. Khi tôi bước qua rs.open nó nói "lỗi xảy ra. [,,,,,,]" mà không phải là rất chi tiết !!!! – Belliez

3

Thực ra, CursorLocation đóng một vai trò quan trọng trong trường hợp này. Sử dụng rs.CursorLocation = adUseClient để đặt vị trí con trỏ và thử.

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

Tôi đã thử điều này và nó vẫn trả về -1 – Belliez

+0

Mặc dù CursorLocation điều khiển hành vi, nó cũng phụ thuộc vào trình điều khiển bạn đang sử dụng. Trên thực tế rs.CursorLocation = adUseClient cho phép các con trỏ của trình điều khiển được sử dụng. Xem tài liệu của trình điều khiển bạn đang sử dụng (Microsoft.SQLSERVER.CE.OLEDB.3.5) cho khả năng con trỏ của nó. Trình điều khiển CE có thể không cung cấp. Trong trường hợp đó, bạn có thể tìm kiếm một trình điều khiển được nâng cấp. – Kangkan

+0

Bạn có thể đặt thuộc tính CursorLocation của đối tượng kết nối không? – Kangkan

0

Từ bộ nhớ với làm việc với VB6/ADO một thời gian dài trước đây, lĩnh vực .RecordCount không trả lại dữ liệu có ý nghĩa cho đến khi bạn đã chuyển đến cuối recordset.

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

Mặc dù vậy, bạn sẽ cần đảm bảo bạn có loại con trỏ thích hợp (nghĩa là không chuyển tiếp). Chỉ có một giải pháp khác mà tôi có thể nghĩ là thực hiện SELECT COUNT (*) TỪ myTestTable riêng biệt, v.v. nhưng điều này có vấn đề với việc thay đổi dữ liệu giữa cuộc gọi đó và một sự kiện thực sự trả về các hàng.

1

Với Compact thuộc tính con trỏ mặc định là adOpenForwardOnly để cải thiện hiệu suất. Như RecordCount như vậy được trả về là "-1" có nghĩa là nó không có sẵn, chứ không phải là trống. Điều này là do thiết kế vì số lượng bản ghi trong một con trỏ động có thể thay đổi và dẫn đến ping qua lại giữa máy chủ khách để duy trì độ chính xác. Tuy nhiên, nếu số lượng bản ghi là rất quan trọng, hãy thử đặt nó để sử dụng adOpenKeyset hoặc adOpenStatic với con trỏ phía máy chủ.

-1

Mã sau đây trả về số tiền chính xác ...

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

điều này sử dụng cơ sở dữ liệu Access, không phải cơ sở dữ liệu SDF. – Belliez

1

Dưới mã có thể giúp bạn,

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

Kiểm tra Recordset tài sản

Các theo là kết quả mà giá trị RecordCount trở bởi mã 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

Đây là một giải pháp cho bạn rằng tôi đã sử dụng

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

Hãy thử sử dụng đoạn mã sau nếu vẫn trả về -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

Bạn có thể thử một cái gì đó như thế này ..

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