当前位置:编程学习 > VB >>

送分100分:简单的关于变量的生存期的问题。

下面这个函数中:
 
Public Function SelectSQL(ByVal SQLStr As String, ByRef msg As String) As ADODB.Recordset 
'执行SQL语句,并ADODB.Recordset返回给 SELECTSQL 
    Dim Conn As ADODB.Connection 
    Dim rst As ADODB.Recordset 
    Dim sTokens() As String 
    '出错处理 
    On Error GoTo ErrorHandle 
    '判断SQL语句 
    sTokens = Split(SQLStr) 
    If InStr("SELECT", UCase((sTokens(0)))) Then 
        '打开数据库连接 
        If OpenConn(Conn) Then                      '如果打开连接成功,就进行查询操作 
            Set rst = New ADODB.Recordset 
            rst.CursorLocation = adUseClient 
            rst.Open Trim$(SQLStr), Conn, adOpenDynamic, adLockOptimistic    '执行查询操作 
            Set SelectSQL = rst 
            msg = "查询到" & rst.RecordCount & " 条记录! " 
        End If 
    Else 
        msg = "SQL语句有误:" & SQLStr 
    End If 
Finally_Exit: 
    Set rst = Nothing 
    Set Conn = Nothing 
    Exit Function 
ErrorHandle:        '如果SQL语句执行出错,提示出错信息并转到Finally_Exit 
    MsgString = "查询错误: " & Err.Description 
    Resume Finally_Exit 
End Function 

问题如下: 
1、Set SelectSQL = rst  作用是什么?(是引用,还是将RST的记录集复制一份给SELECTSQL,还是其他?) 
2、Finally_Exit: 
    Set rst = Nothing 
    Set Conn = Nothing 
  以上二句执行完后,变量RST和CONN不是被注销了吗,即使不是这样,这两个变量是两个局部变量,函数一执行完,不也消失了吗。
   SelectSQL岂不是什么也没有了? 这个函数怎么能返回一个ADODB.Recordset。
--------------------编程问答-------------------- 这个过程类似于张三(rst)递给李四(SelectSQL)一件东西。
过程:
张三递,李四接 (Set SelectSQL = rst)
然后张三松手    (Set rst = Nothing)
只要李四接住了东西,张三就可以去死了。
--------------------编程问答--------------------
引用 1 楼 yachong 的回复:
这个过程类似于张三(rst)递给李四(SelectSQL)一件东西。
过程:
张三递,李四接 (Set SelectSQL = rst)
然后张三松手    (Set rst = Nothing)
只要李四接住了东西,张三就可以去死了。

高,我想了半天也没有想到好的措辞,,顶 --------------------编程问答--------------------
引用 1 楼 yachong 的回复:
这个过程类似于张三(rst)递给李四(SelectSQL)一件东西。
过程:
张三递,李四接 (Set SelectSQL = rst)
然后张三松手    (Set rst = Nothing)
只要李四接住了东西,张三就可以去死了。

呵呵,这个比喻挺形象嘛。 --------------------编程问答-------------------- 是不是说在
        Set rst = New ADODB.Recordset 
        rst.CursorLocation = adUseClient 
        rst.Open Trim$(SQLStr), Conn, adOpenDynamic, adLockOptimistic    '执行查询操作 
第三句执行之后CONN就没有用了,可以注销了? --------------------编程问答--------------------
引用 1 楼 yachong 的回复:
.............
只要李四接住了东西,张三就可以去死了。


--------------------编程问答--------------------
引用 4 楼 elvasam 的回复:
是不是说在
        Set rst = New ADODB.Recordset
        rst.CursorLocation = adUseClient
        rst.Open Trim$(SQLStr), Conn, adOpenDynamic, adLockOptimistic    '执行查询操作
第三句执行之后CONN就没有用了,可以注销了?

对呀,只要后面没有再调用到conn和rst,就可以注销 --------------------编程问答-------------------- --------------------编程问答-------------------- 对于对象的赋值,需要使用Set语句。
并且对象使用完之后,要关闭(有关闭的,如记录集),并且销毁,否则会出现内存泄漏。
虽然函数执行完,对象生存期已过,但是不会自动销毁的。 --------------------编程问答-------------------- 只要李四接住了东西,张三就可以去死了。 

强一个 --------------------编程问答-------------------- 以上的这函数应该不能正常使用。
假设有一个函数调用
dim rs as adodb.recordset
dim imsg as string
set rs = SelectSQL("select * from db",imsg)
msgbox imsg 
do while not rs.eof
   msgbox rs.fields(0).value
   rs.movenext
loop
执行的时候肯定会出错。因为本地rs需要的宿主都已经“去死了”
除非在函数里用
set SelectSQL = rst.clone()
将rst脱机到本地才能正常使用 --------------------编程问答-------------------- 兄弟们简直太有才了 --------------------编程问答-------------------- 建议楼主在
    Set rst = Nothing 
    Set Conn = Nothing 

前加上

rst.Close
Conn.Close

我的意思是避免循环引用导致COM不能释放 --------------------编程问答--------------------
Set SelectSQL = rst

VB 中,函数返回值就是一个与函数同名的变量。
这句语句就是将 rst 赋给返回值变量,对象的赋值都是引用,这时变量 rst 和 SelectSQL 都引用同一个 RecordSet 对象实例。

[code=VB]Finally_Exit: 
    Set rst = Nothing 
    Set Conn = Nothing 
分别断开变量 rst 和 Conn 与对象实例的引用,按照标准的术语是减少对象实例的引用计数。
不过由于 RecordSet 对象实例被 SelectSQL 变量引用,而 Connection 对象又被 RecordSet 对象引用,按照规则,被引用的对象(引用计数非零)的对象不释放——即这两句语句并不会产生注销。
同样,即使不写这两句,过程结束是也一样会断开引用,不过效果一样,也不会注销。
补充:VB ,  数据库(包含打印,安装,报表)
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,