Я пытаюсь заставить некоторый старый код VB6 работать с Компактным SQL Server.
Я могу соединить, открыть базу данных, и все кажется хорошо. Я могу работать, вставляют избранные команды, которые работают.
Однако свойство ADODB.Recordset RecordCount всегда возвращается-1 даже при том, что я могу получить доступ к Полям и видеть данные. При изменении CursorLocation = adUseClient вызывает проблему, когда executung 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
Любой совет был бы с благодарностью принят.
Замените Set rs = mCmd.Execute
на:
set rs = new ADODB.Recordset
rs.Open "select * from myTestTable", mDBConnection, adOpenDynamic, adLockOptimistic
adOpenDynamic
разрешит переход вперед / назад прочтите, чтобы узнать количество записей.
На самом деле 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
Это результат типа курсора, используемого для доступа к данным, в этом сообщении описывается проблема и возможные исправления.
http://www.devx.com/tips/Tip/14143
РЕДАКТИРОВАТЬ
Прошу прощения за то, что не стал более внимательным к тому факту, что вы имели дело с Compact. С Compact ситуация аналогична той, на которую я ссылался, поскольку он по умолчанию использует курсоры только вперед (которые не поддерживают счетчик строк), но есть два других типа курсоров, доступных, как описано в приведенной ниже ссылке.
В Compact атрибутом курсора по умолчанию является adOpenForwardOnly для повышения производительности. В этом случае RecordCount возвращается как "-1", что означает, что он недоступен, а не пуст. Это сделано специально, потому что количество записей в динамическом курсоре может измениться и привести к необходимости пинговать туда-сюда между сервером и клиентом для поддержания точности. Однако, если количество записей очень важно, попробуйте настроить его на использование adOpenKeyset или adOpenStatic с курсором на стороне сервера.
Из памяти при работе с VB6 / ADO давным-давно поле .RecordCount не возвращает значимые данные, пока вы не переместитесь в конец набора записей.
rs.MoveLast
rs.MoveFirst
Debug.Print rs.RecordCount
Хотя при этом вам необходимо убедиться, что у вас есть соответствующий тип курсора (т.е. не только вперед).
Единственное другое решение, которое я могу придумать, - это выполнить отдельный SELECT COUNT (*) FROM myTestTable и т. Д., Но у этого есть проблемы с изменением данных между этим вызовом и тем, который фактически возвращает строки.
Этот следующий код точно возвращает счетчик пересчета ...
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