VB6 ADODB.Recordset RecordCount 属性总是返回 -1
Posted
技术标签:
【中文标题】VB6 ADODB.Recordset RecordCount 属性总是返回 -1【英文标题】:VB6 ADODB.Recordset RecordCount property always returns -1 【发布时间】:2011-01-17 23:12:59 【问题描述】:我正在尝试让一些旧的 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
我们将不胜感激地接受任何建议。
【问题讨论】:
【参考方案1】:实际上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
【讨论】:
虽然 CursorLocation 驱动行为,但它同样取决于您使用的驱动程序。实际上 rs.CursorLocation = adUseClient 允许使用驱动程序的光标。有关光标功能,请参阅您正在使用的驱动程序文档 (Microsoft.SQLSERVER.CE.OLEDB.3.5)。 CE 驱动程序可能不提供它。在这种情况下,您可能会寻找升级的驱动程序。 能否也设置连接对象的 CursorLocation 属性? 设置为 aduseserver THE CONNECTION 而不是记录集。使用新的/其他连接【参考方案2】:这是用于访问数据的游标类型的结果,这篇文章涵盖了问题和可能的修复。
http://www.devx.com/tips/Tip/14143
编辑
我很抱歉没有更注意您与 Compact 打交道的事实。使用 Compact 时,情况与我提到的情况类似,因为它默认使用仅向前游标(不支持行计数),但还有其他两种可用的游标类型,如下面的链接中所述。
http://support.microsoft.com/kb/272067
【讨论】:
尝试了这两种方法,但都未能执行“select * from myTestTable”。顺便说一句,如果我通过 Sql Server Management Studio 2008 打开 sdf,则 sql 可以工作并返回 11 行。【参考方案3】:从很久以前使用 VB6/ADO 的内存中,.RecordCount 字段不会返回有意义的数据,直到您移动到记录集的末尾。
rs.MoveLast
rs.MoveFirst
Debug.Print rs.RecordCount
尽管如此,您需要确保您具有适当的光标类型(即,不仅仅是向前)。
我能想到的唯一其他解决方案是执行单独的 SELECT COUNT(*) FROM myTestTable 等,但这会导致该调用与实际返回行的调用之间的数据发生变化。
【讨论】:
【参考方案4】:对于 Compact,默认光标属性是 adOpenForwardOnly 以提高性能。因此,RecordCount 返回为“-1”,这意味着它不可用,而不是空白。这是设计使然,因为动态游标中的记录数可能会更改并导致在客户端服务器之间来回 ping 以保持准确性。但是,如果记录数很重要,请尝试将其设置为使用带有服务器端游标的 adOpenKeyset 或 adOpenStatic。
【讨论】:
【参考方案5】:检查记录集属性
以下是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 |
+------------------+-------------------+-------------+---------------+--------------+
【讨论】:
【参考方案6】:这是我使用的解决方案
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
【讨论】:
【参考方案7】:将Set rs = mCmd.Execute
替换为:
set rs = new ADODB.Recordset
rs.Open "select * from myTestTable", mDBConnection, adOpenDynamic, adLockOptimistic
adOpenDynamic
将允许向前/向后读取以获取您的记录数。
【讨论】:
我试过了,但是当我运行 rs.open 时出现错误:“发生错误。[,,,,,,]” 发生的错误是我在评论中提到的错误。当我越过 rs.open 时,它说“发生错误。[,,,,,,]”这不是很详细!!!!【参考方案8】:如果仍然返回 -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
【讨论】:
【参考方案9】:你可以试试这样的..
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
【讨论】:
【参考方案10】:以下代码可能对您有所帮助,
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
【讨论】:
【参考方案11】: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
【讨论】:
【参考方案12】:您必须将 CONNECTION 设置为 aduseClient,没有记录集 并且小心只设置一个新的连接,如果你在你的项目中使用相同的连接,你可能会得到其他错误。
与 aduseclient 建立新的联系
Dim Sql As String
Dim CnCommand As New ADODB.Connection
On Error GoTo VerError:
Dim Comando As ADODB.Command
Set Comando = New ADODB.Command
CnCommand.ConnectionString = Cn.ConnectionString 'your exist connection in application
CnCommand.Open
CnCommand.CursorLocation = adUseClient
Set Comando.ActiveConnection = CnCommand
'Comando.ActiveConnection.CursorLocation = adUseClient
Comando.Parameters.Append Comando.CreateParameter("@Usuario", adInteger, adParamInput, , V_General.Usuario.Codigo)
Comando.CommandType = adCmdStoredProc
Comando.CommandText = "SP_Contratac"
Dim Rs As Recordset
Set Rs = New ADODB.Recordset
Set Rs = Comando.Execute()
【讨论】:
【参考方案13】:以下代码准确返回记录计数...
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
【讨论】:
这使用 Access 数据库,而不是 SDF 数据库。以上是关于VB6 ADODB.Recordset RecordCount 属性总是返回 -1的主要内容,如果未能解决你的问题,请参考以下文章