如何解决取ADO的Recordset对象的RecordCount属性总是-1问题

1.如何解决取ADO的Recordset对象的RecordCount属性总是-1问题

最近在用asp做网页后台时,遇到了一个烦人的问题,RecordSet对象的RecordCount和PageCount均为-1.不能直接获取RecordCount属性,我就想了其他的笨办法代替,比如,利用了SQL的集函数select Count(*) as count from table,这样count中就存储了RecordSet的属性值;或者,利用一个变量存储,在游标从头到尾的搜索过程中,这个变量逐次加一,最终就得到了该属性:
<%dim i
i=0
set rs=conn.Open "select * from table"
do while not rs.EOF
i=i+1
rs.MoveNext
Loop
%>
   可是,接下来要用到PageCount属性来实现分页(AbsolutePage:指定当前页;PageCount:返回记录集中的逻辑页数;PageSize:指定一个逻辑页中的记录个数,缺省值是10.)这种方法行不通了,没办法,就开始到处搜集信息:
   首先让我们来看看怎么样获得记录集RecordSet,有以下几种:
<%
set conn = Server.CreateObject("ADODB.Connection")
set rs = conn.Open(sqlstring)
%>

另外一种方式:

<% set conn =Server.CreateObject("ADODB.Connection")
set cmd = Server.CreateObject("ADODB.Commend")
cmd.ActiveConnect = conn
cmd.StringText = "Select * from Table"
set rs = cmd.Open conn %>

而另外一种办法就是:
<%
set rs = Server.CreateObject("ADODB.Recordset")
rs.open sql,conn,
打开方式,锁类型 %>
参数一表示游标类型,如下设置:
参数1            意    义
0 只读,   数据只能向下移动
1 可读写,数据可以自由移动,多用户下别人不能看到新增数据(除非重启动)
2 可读写,数据可以自由移动,多用户下别人可以看到新增数据
3 只读 , 数据可以自由移动

参数2表示锁定类型,如下:
参数2          意    义
1 默认值,   只读
2                   悲观锁定
3                   乐观锁定
4                  批次乐观锁定
也就是说第一个参数为1或2的时候,才能有recordcount

所以也可以用recordset.open打开数据源:
   rs.CursorLocation = adUseClient
   rs.CursorType = adOpenStatic
   rs.open sqlstring,conn

   在我的程序中,改为第二种打开方式就可以正确访问RecordSet的那些属性了.具体就是:
rs.Open sqlstring,conn,1,3
   那么CursorLocation和CursorType到底是什么东西,能产生这么大的影响?
(1)CursorLocation:
设置或返回游标引擎的位置, 可设置为以下某个常量的长整型值:
adUseNone:   没有使用游标服务.(该常量已过时并且只为了向后兼容才出现)
adUseClient:
    使用由本地游标库提供的客户端游标。本地游标引擎通常允许使用的许多功能可能是驱动程序提供的游标无法使用的,因此使用该设置对于那些将要启用的功能是有好处的。adUseClientBatch 与 adUseClient 同义,也支持向后兼容性。
到这里大家应该明白为什么我们的游标会出问题及解决办法了.
adUseServer:
    默认值。使用数据提供者或驱动程序提供的游标。这些游标有时非常灵活,对于其他用户对数据源所作的更改具有额外的敏感性。但是,Microsoft Client Cursor Provider(如已断开关联的记录集)的某些功能无法由服务器端游标模拟,通过该设置将无法使用这些功能。
    注:当用于客户端(ADOR)RecordSet或Connection对象时,只能将CursorLocation属性设置为adUseClient.
(2)CursorType:
    指示在RecordSet对象中使用的游标类型,设置或返回以下某个CursorTypeEnum值:
adOpenForwardOnly(=0):
    仅向前游标,默认值.与静态游标相同,但只能在记录中向前滚动.当需要在记录集中单向移动时,可用于提高性能.
adOpenKeyset(=1):
    键集游标。尽管从您的记录集不能访问其他用户删除的记录,但除无法查看其他用户添加的记录外,键集游标与动态游标相似。仍然可以看见其他用户更改的数据。
adOpenDynamic(=2):
    动态游标。可以看见其他用户所作的添加、更改和删除。允许在记录集中进行所有类型的移动,但不包括提供者不支持的书签操作。
adOpenStatic(=3):
    静态游标。可以用来查找数据或生成报告的记录集合的静态副本。另外,对其他用户所作的添加、更改或删除不可见。
    注:如果将CursorLocation 属性设置为 adUseClient,则只支持 adOpenStatic 的设置。如果设置了不支持的值,不会导致错误,并将使用最接近支持的 CursorType。
    当用于客户端 (ADOR) Recordset 对象时,只能将 CursorType 属性设置为 adOpenStatic。
   
   另外在查资料的过程中,发现网上也有好多人在问这个问题,看他们是怎么解决的,顺便汇总一下各方面的资料:
  
    打开方式有问题吧,后两个参数设为3,1试试,想更改用3,3,如果既要记录数又要允许修改就试1,3
rs.CursorLocation= adUseClient    '设为adUseClient
rs.Open"sql语句",conn                        '或者游标类型为adOpenStatic
将返回记录总数

当CursorType=1时,rs.RecordCount是不可用的,将其设为3即可。

你只要将RecordSet的游标类型设置为客户端游标类型就行了:
设置cursorlocation=adUseServer

这个问题我碰到过,打开参数只有在为adopenstastic的情况下recordcont属性才能正确显示数据集中的记录值Recordset对象的游标类型会影响是否能够确定记录的数目。对仅向前游标,RecordCount性将返回-1,对静态或键集游标返回实际计数,对动态游标取决于数据源,返回-1或实际计数。
   RS.OPEN SQL,CONN,A,B    A为游标类型,B为锁类型
   A: adOpenForwardOnly(=0) 只读,且当前数据记录只能向下移动
      adOpenKeySet(=1) 只读,当前数据记录可自由移动
      adOpenDynamic(=2) 可读写,当前数据记录可自由移动
      adOpenStatic(=3) 可读写,当前数据记录可自由移动,可看到新增记录
   B: adLockReadOnly(=1) 缺省锁定类型,记录集是只读的,不能修改记录
      adLockPessimistic(=2) 悲观锁定,当修改记录时,数据提供者将尝试锁定记录以确保成功地编辑记录。只要编辑一开始,则立即锁住记录。
      adLockOptimistic(=3) 乐观锁定,直到用Update方法提交更新记录时才锁定记录。
      adLockBatchOptimistic(=4) 批量乐观锁定,允许修改多个记录,只有调用UpdateBatch方法后才锁定记录。 当不需要改动任何记录时,应该使用只读的记录集,这样提供者不用做任何检测。对于一般的使用,乐观的锁定可能是最好的选择,因为记录只被锁定一小段时间,数据在这段时间被更新。这减少了资源的使用。
     引用:

     记录集是否可写不是由光标类型决定的,而是由锁类型决定的。第一种光标(adOpenForwardOpnly)只能向前移动,第二种光标(adOpenStatic)可自由移动。但它们只决定了记录集是静态的,而不是“只读”的。而后面两种也不是“可读写”的,而是“动态”的。

    记录集分动态、静态两种,区别在于,记录集在打开的过程中,是否实时反映用户对数据库的更改(可能是当前访问数据集的用户,也可能是其他用户)。

   adOpenForwardOnly和adOpenStatic这两种属静态类型,当前用户打开记录集后,记录集就保持不变一直到关闭后再次打开它。在这过程中如果数据库中的相应记录发生改变,在当前用户是看不到的。

    adOpenDynamic和adOpenKeyset这两种则属动态类型,记录集会反映出数据库中相应记录的更改,他们两者的区别在于:adOpenDynamic是完全动态的,数据库记录的更新、删除、添加都会体现在当前用户所打开的记录集中;而adOpenKeyset则保持当前记录集的个数不变,它只体现更新操作,不体现删除和添加操作。

    另外,建议大家使用相应的ADO常量,而不是用一些让人摸不着头脑的数字。ADO常量非常有用,建议大家去记这些常量,而不是记数字。常量由英文单词组成,可以提高代码的可读性,更重要的是帮助我们理解常量所充当的作用。
   
    通常用于单纯显示的记录集,只需要用只向前、只读类型即可,而这两个属性是默认的,所以可以不设置,如:RS.Open strSQL, conn, adOpenForwardOnly, adLockReadOnly 等同于 RS.Open strSQL, Conn 打开这种记录集的执行效率是最高的!例外的是需要对记录集进行分页,这时必须替换adOpenForwardOnly为其它的,比如adOpenStatic就不错。而通常大家使用的rs.Open sql, cn, 1, 1则需要更多的时间来打开,而应用中通常并不需要。

ADO的RECORDSET的RECORDCOUNT属性总是为-1

    现象
    ====
    当在服务器端请求RecordCoun时会返回-1。这是因为ActiveX Data Objects (ADO) 2.0中的CursorType是adOpenForwardonly或者adOpenDynamic。如果是ADO 1.5,只发生在cursortype是adOpenForwardonly的时候。如果使用OLEDB provider for JET和SQL Server产生的结果可能不同,这依赖于数据库的提供者。
    提供者可能不支持某些CursorTypes。当你选择的CursorType不被支持时,提供者将选择最接近于你所请求的CursorType。请参考你的提供者的文档。此外,请注意不是所有的LockType和CursorType的组合都可以同时工作。改变LockType将强制改变CursorType。请确定使用调试来检查CursorType的值。
    
    原因
    =====
    
    在动态的游标中纪录号可能改变。Forward only的游标无法返回RecordCount。
    
    解决办法
    ==========
    使用adOpenKeyset(=1)或者adOpenStatic(=3)作为服务器端游标或者客户端游标。客户端只使用adOpenStatic作为CursorTypes,而不管你选择什么样的CursorType。
    
    状态
    ======
    
    这个形式是设计决定的。
    
    更多信息
    ================
    
    重复行为的步骤
    ---------------------------
    
    1. Open a standard .exe project in Visual Basic. From theProject menu, choose References. Select either the Microsoft Active Data Object1.5 Library or the Microsoft Active Data Object 2.0 Library.
    
    2. Paste the following code in the form code window:
    
     Option Explicit
     Dim rs As ADODB.Recordset
    
     Private Sub Form_Load()
     'set up rs
     Set rs = New ADODB.Recordset
     rs.CursorLocation = adUseServer
     rs.Open "Select ProductID from products",& _
     "Provider=Microsoft.Jet.OLEDB.3.51;" & _
     "Data Source=d:\vb5_win95\nwind.mdb", _
     adOpenDynamic, adLockUnspecified
    
     Debug.Print rs.RecordCount
     End Sub
    
     3. Replace the preceding Data Source with a DataSource on your computer. Run the preceding form and note the record count.Change the CursorType to adOpenForwardonly and note the record count.
    
     4. Change the CursorLocation to adUseClient andexperiment with the different CursorTypes. In all cases the correct recordcount returns.
   

    打开 Recordset 前设置 LockType 属性可指定打开时提供者应该使用的锁定类型。读取该属性可返回在打开的Recordset 对象上正在使用的锁定类型。Recordset 关闭时 LockType 属性为读/写,打开时该属性为只读。

    提供者可能不支持所有的锁定类型。如果某提供者不支持所需的 LockType设置,则将替换为其他类型的锁定。要确定 Recordset 对象可用的实际锁定功能,请通过 adUpdate 和 adUpdateBatch 使用 Supports 方法。

    如果 CursorLocation 属性被设置为 adUseClient,将不支持 adLockPessimistic 设置。设置不支持的值不会产生错误,因为此时将使用支持的最接近的 LockType 的值。

    远程数据服务用法   当在客户端 (ADOR) 的 Recordset 对象上使用时,LockType 属性只能设置为 adLockOptimisticBatch。

rs.cursorlocation=3    '加上这一行
rs.open   sql,conn,1,1

Recordset对象所有的属性和方法作者:
Recordset 属性 adOpenForwardOnly adOpenKeysetadOpenDynamic adOpenStatic
AbsolutePage     不支持 不支持 可读写 可读写
AbsolutePosition 不支持 不支持 可读写 可读写
ActiveConnection 可读写 可读写 可读写 可读写
BOF               只读 只读 只读 只读
Bookmark         不支持 不支持 可读写 可读写
CacheSize        可读写 可读写 可读写 可读写
CursorLocation   可读写 可读写 可读写 可读写
CursorType       可读写 可读写 可读写 可读写
EditMode           只读 只读只读 只读
EOF               只读 只读 只读 只读
Filter           可读写 可读写可读写 可读写
LockType         可读写 可读写 可读写 可读写
MarshalOptions   可读写 可读写 可读写 可读写
MaxRecords       可读写 可读写 可读写 可读写
PageCount        不支持 不支持 只读 只读
PageSize         可读写 可读写 可读写 可读写
RecordCount      不支持 不支持 只读 只读
Source           可读写 可读写可读写 可读写
State            只读只读 只读 只读
Status           只读 只读只读 只读
AddNew           支持 支持支持 支持
CancelBatch      支持 支持 支持 支持
CancelUpdate     支持 支持 支持 支持
CancelUpdate     支持 支持 支持 支持
Close            支持支持 支持 支持
Delete           支持 支持支持 支持
GetRows          支持 支持 支持 支持
Move             不支持支持 支持 支持
MoveFirst        支持 支持 支持 支持
MoveLast         不支持 支持 支持 支持
MoveNext          支持 支持 支持 支持
MovePrevious     不支持 支持 支持 支持
NextRecordset    支持 支持 支持 支持
Open             支持支持 支持 支持
Requery          支持 支持 支持 支持
Resync           不支持 不支持支持 支持
Supports         支持 支持 支持 支持
Update           支持 支持支持 支持
UpdateBatch      支持 支持 支持 支持

综上所述,我们可以考虑以下几条意见:

   意见1:
    在打开recordset记录集的时候,如果参数3(就是CursorType)为键盘索引或者向前索引时(CursorType参数为0or 1),为了提高处理速度,recordset纪录是一条一条给你的,而不是一下子都给你的。解决方法是使用动态或静态索引(CursorType参数为2 or 3)
    
    意见2:
    因为在c/s结构中,记录集是分页存储的,当你从服务器请求数据时,它不会给你全部数据。最好用rs.getrows()的到所有记录行
    
    意见3:
    将ADO连接的CursorLocation属性设置为客户端:rs.CursorLocation = adUseClient就行了。
    
    意见4:
    如果只是要判断ADO的RECORDSET为空,用RECORDSET.EOF=TRUE就行了!我从不用RECORDSETCOUNT=0判断是否为空!
    
    意见5:
    如果ADO的RECORDCOUNT为-1,只要设置CursorType参数为2 or 3就行啊。

2. VB数据库编空字段的处理

在往SQL Server数据库中添加记录时,每个字段必须给予明确赋值(即在没有给数据表设定缺省规则或给每个字段设定缺省值的情况下),否则便发生错误。因此我用VB编写了一个处理函数,将其放入标准模块,以供相应程序调用。函数首先判断是否给字段赋值,若没有,则根据字段类型的不同赋予不同数值(数字赋零,字符赋空格)。程序如下:

  ′zd变量采用变体类型

  Functionnonull(zd As Variant) As Variant

  IfIsNull(zd) Then

  ′字段没有赋值,判断其类型

  If zd.Type =12 Then

  ′字符型字段,赋空格

  nonull =" "

  Else

  ′数字型字段,赋0

  nonull = 0

  End If

  Else

  nonull = zd

  End If

End Function

3.彻底解决VB6~VB2005中连接ACCESS数据库(及带密码)问题

2008年05月26日 星期一 13:31在Visual Basic中连接和使用Access数据库中,为了确保数据库中信息的安全,往往要求对数据库文件进行加密,以防止非法用户通过其它的常规手段(如使用ACCESS将数据库文件打开、修改)将其打开。那么,在Visual Basic中如何建立与加密的数据库的连接呢?介绍如下(以下部分内容摘自网络)。

  一、建立数据库

  因为在VisualBasic 6.0中有的数据库连接方式不支持Access2000版本格式的数据库,为了便于说明问题,本文所提的数据库以Access 97版本数据库为例。

  在MicrosoftAccess 97中建立一个数据库,如:ssgl.mdb,并设置密码,如:“1234”,再将数据库文件和VB中创建的工程文件放在同一目录下。

  如果用户的计算机上只有Access2000的话,可以先在Access2000中建立ssgl.mdb数据库,并设置密码,再用Access 2000中的“数据库实用工具”将数据库转换成Access97版本的格式。

  当然也可以直接在VisualBasic 6.0集成开发环境中通过“可视化数据管理器”来创建数据库,再到Access 97中设置密码。

  通过对数据库文件设置密码,一般情况下,非法用户就不能用常规的手段打开数据库了,对数据库中的信息起到了一定的安全和保密作用。

  二、连接加密的Access数据库

  在VisualBasic 6.0中,要建立与数据库的连接,可采用的技术手段很多,如:数据控件、数据对象、数据环境设计器等。开发人员可以根据自身的条件和用户的需求进行选择。

  限于篇幅,下面只介绍加密的Access数据库与没有加密的Access数据库在连接时的不同之处。关于没有加密的数据库的连接及访问的方法读者可以参阅其它资料。

  1、使用控件

  ① Data控件

  Data控件是Visual Basic 6.0中的一个内置数据控件,可以通过设置Data控件的connect、DatabaseName、RecordSource属性实现对数据库的连接和访问。 通过Data控件连接加密的数据库的方法有两种:

  一种方法是在设计状态时,在“属性窗口”中将Data控件的connect属性的缺省值”Access”改为”; pwd=1234”即可,其它属性的设置方法与没有加密的Access数据库的连接相同。

另一种方法是在运行时,通过代码对connect属性赋值来实现。如:

Data1.connect=”; pwd=1234”

Data1.DatabaseName=APP.path + “\ssgl.mdb”

  其中,”1234”为Access数据库文件ssgl.mdb的密码,下同。

  ②Adodc控件

  Adodc控件是一个ActiveX控件,它使用Microsoft ActiveX DataObjects(ADO)创建到数据库的连接。使用Adodc控件之前,要先将Adodc控件添加到控件工具箱中。方法如下:在VB 6.0种选择“工程”菜单,再点击“部件”菜单项,在弹出的“部件”对话框中选中“Microsoft ADO Data Control6.0(OLEDB)”选项即可。

  通过Adodc控件连接加密的数据库的方法也有两种:

  一种方法是在设计状态时,在“属性窗口”中,对Adodc控件的ConnectionString属性设置一个有效的连接字符串,并在连接字符串后增加上”; JetOLEDB: DataBase password=1234”,再设置Adodc控件的CommandType、RecordSource的属性就可以创建到加密的数据库的连接了。

  另一种方法是在运行时,通过代码动态地设置ConnectionString、CommandType和RecordSource属性来创建连接。 只要在ConnectionString属性的有效连接字符串后增加上”; Jet OLEDB: DataBasepassword=1234”即可。

  2、使用数据对象

  ① DAO数据对象

  要能正确引用DAO数据对象来建立与数据库的连接,应先在VB集成开发环境中选择“工程”菜单,再点击“引用”菜单项,在弹出的“引用”对话框选择“Microsoft DAO 3.51 Object Library”选项来添加DAO数据对象类型库。

  接下来就可用如下代码来建立到加密的Access数据库ssgl.mdb的连接。

Dim db AS DataBase

Set db=OpenDataBase(App.path + “\ssgl.mdb” , False , False , ” ; pwd=1234”)

  ② ADO数据对象

  ADO是Microsoft推出的处理关系数据库和非关系数据库中信息的最新技术,也是Microsoft推崇的用于数据连接和访问的技术。在VB 6.0中,Adodc控件、ADO数据对象及DataEnvironment(数据环境设计器)都采用的是ADO技术,因而它们处理加密的Access数据库的方法类似。

  要能正确引用ADO数据对象,应在VB 6.0集成开发环境中选择“工程”菜单,再点击“引用”菜单项,在弹出的“引用”对话框中选中“Microsoft ActiveX Data Objects 2.1 Library”选项来添加ADO数据对象类型库。

  可用如下代码来建立到加密的Access数据库ssgl.mdb的连接。

Dim cnn AS ADODB.Connection

Dim rst AS ADODB.Recordset

Set cnn=New ADODB.Connection

Cnn.Provider= ”Microsoft.Jet.OLEDB.3.51”

Cnn.ConnectionString= ”Data Source=” & App.path & ”\ssgl.mdb;” & _

” ;Jet OLEDB:Database password=1234”

cnn.Open

  ③ 使用DataEnvironment(数据环境设计器)

  有两种方法可以通过DataEnvironment连接到加密的Access数据库:

  一种方法是在设计状态时,在DataEnvironment的connection对象的ConnectionSource属性的有效连接字符串后加上” ;Jet OLEDB: Database password=1234”

 另一种方法是在DataEnvironment_Initialize()事件中编写如下代码:

Private sub DataEnvironment_Initialize( )

Dim strconn AS string

Strconn=” Provider=Microsoft.Jet.OLEDB.3.51;” & _

”Data Source=” & App.path & “\ssgl.mdb;” & _

”; Jet OLEDB: Database password=1234”
DataEnvironment1.connection1.connectionstring=strconn

End sub

  以上方法及相关代码已在Windows98操作系统环境,VisualBasic 6.0中调试、验证并通过。

以下是本站的补充:
由于现在用户普遍使用ACCESS2003,使用VB6连接数据库便产生了新的麻烦。也就是,即使在VB中使用
ADO连接方式,但ACCESS2003建立的数据库也会出现无法连接(显示“找不到ISAM”)的问题。实践后,用以下方法坚决比较简单:
1.针对DATA控件:由于它本身就不支持ACCESS2003,故可以在ACCESS2003中建立好数据库;然后,用独占方式打开该数据库文件,用添加密码的方式设置密码;关闭后,用普通方式再次打开该数据库文件,然后将其转换为ACCESS97数据库。这样,在连接到VB应用程序中就正常了。
2.针对ADO数据编程:虽然,ADO本身支持ACCESS2003,但数据库文件加了密码后,就会出现无法连接(显示“找不到ISAM”)的问题;这里,就采用“针对DATA控件”的方法来解决ADO中遇到的问题,这样,就同样能正常打开使用数据库了,只是该数据库已经转换称了ACCESS97格式。本方法在VB中如下:

connstring ="provider=microsoft.jet.oledb.4.0;" & "data source="& App.Path & "\db1.mdb;" & "Jet OLEDB: Databasepassword=12345"


其实ACCESS97格式足够我们普通使用了。以上应用在windows XPSP2+ACCESS2003+VB6环境下正常通过。

补充:
现在,对在高版本VB中的连接带密码的数据库连接字编写做补充!以VB2005为例,连接ACCESS数据库(带密码)时,也会遇到:“找不到可安装的isam”问题,解决如下:
假设,ACCESS数据库文件db1.mdb放置在项目的窗体文件的同文件夹下,密码为123。完整的代码如下

connstring="Provider=Microsoft.Jet.OLEDB.4.0;DataSource=|DataDirectory|\db1.mdb;Persist Security Info=True;Jet OLEDB:DatabasePassword=123"
也可以简化上述代码:

connstring="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db1.mdb;Persist SecurityInfo=True;Jet OLEDB:Database Password=123"

以上代码中,connstring是预先定义的string变量,作为连接用字符串。在各个VB版本中调试均通过!

小体会:自己尝试了下,发现用VB6.0连接带密码的access 2000格式的数据库,同样可以成功。代码如下:

sql = "select 滚刀编号,滚刀类型,生产厂家,法向模数mn,法向压力角an,Sn,ha,hb,hc,hd,全齿高h,H,r1,af,ax,滚刀类型标示符 from 滚刀数据表"

Adodc1.ConnectionString ="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & App.Path &"\滚刀数据库.mdb;Persist SecurityInfo=true;Jet OLEDB:Database Password=123"

Adodc1.RecordSource = sql

Adodc1.Refresh

Set DataGrid1.DataSource = Adodc1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值