【问题标题】:Classic ASP disconnected recordsets issue经典 ASP 断开记录集问题
【发布时间】:2014-05-14 17:36:11
【问题描述】:

所以,我被要求更新旧的 Classic ASP 网站。它没有使用参数化查询,并且输入验证很少。为了简化事情,我编写了一个辅助函数,它打开到数据库的连接,设置带有任何参数的命令对象,并创建一个断开连接的记录集 [我想!?! :)] 这是代码:

Function GetDiscRS(DatabaseName, SqlCommandText, ParameterArray)

    'Declare our variables
    Dim discConn
    Dim discCmd
    Dim discRs

    'Build connection string
    Dim dbConnStr : dbConnStr = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
              "Data Source=" & rootDbPath & "\" & DatabaseName & ".mdb;" & _
              "Persist Security Info=False"

    'Open a connection
    Set discConn = Server.CreateObject("ADODB.Connection")
    discConn.Open(dbConnStr)

    'Create a command
    Set discCmd = Server.CreateObject("ADODB.Command")
    With discCmd
        Set .ActiveConnection = discConn
        .CommandType = adCmdText
        .CommandText = SqlCommandText

        'Attach parameters to the command
        If IsArray(ParameterArray) Then
            Dim cnt : cnt = 0
            For Each sqlParam in ParameterArray
                discCmd.Parameters(cnt).Value = sqlParam
                cnt = cnt + 1
            Next
        End If
    End With

    'Create the Recordset object
    Set discRs = Server.CreateObject("ADODB.Recordset")
    With discRs
        .CursorLocation = adUseClient     ' Client cursor for disconnected set
        .LockType = adLockBatchOptimistic
        .CursorType = adOpenForwardOnly
        .Open discCmd
        Set .ActiveConnection = Nothing   ' Disconnect!
    End With

    'Return the Recordset
    Set GetDiscRS = discRS

    'Cleanup
    discConn.Close()
    Set discConn = Nothing
    discRS.Close()                  ' <=== Issue!!!
    Set discRs = Nothing
    Set discCmd = Nothing
End Function

我的问题是,如果我在函数末尾调用discRS.Close(),则返回的记录集不会被填充。这让我想知道记录集是否确实断开了连接。如果我评论那条线一切正常。我还在设置ActiveConnection = Nothing 之前和之后使用discRS 值在函数中做了一些Response.Write(),它正确地返回了记录集值。所以它似乎被隔离到discRS.Close()

我在4guysfromrolla.com 上找到了一篇旧文章,它在函数中发出了记录集Close()。我在其他网站上也看到过同样的事情。我不确定这是一个错误,还是有什么变化?

注意:我使用的是 Visual Studio Express 2013 中内置的 IIS Express

【问题讨论】:

标签: vbscript asp-classic recordset


【解决方案1】:

据我所知,断开连接的记录集是指手动填充的记录集,而不是来自数据库,例如用作多维数组或某种哈希表。

因此,您拥有的不是断开连接的记录集,因为它是从数据库中填充的,并且通过处理它的连接,您只会导致您的代码无法正常工作。

由于您已经在代码中包含Set discConn = Nothing,因此您不必通过记录集或命令对象将其设置为空,它是同一个连接对象。

总而言之,您确实应该去掉代码中的以下几行:

  • Set .ActiveConnection = Nothing ' Disconnect!
  • discRS.Close() ' &lt;=== Issue!!!
  • Set discRs = Nothing

然后为了防止内存泄漏或数据库锁定问题,您应该在使用函数的代码中实际使用记录集后关闭并处理它,例如

Dim oRS
Set oRS = GetDiscRS("mydatabase", "SELECT * FROM MyTable", Array())
Do Until oRS.EOF
    'process current row...
    oRS.MoveNext
Loop

oRS.Close ' <=== Close
Set oRS = Nothing ' <=== Dispose

为避免所有这些麻烦,您可以通过将所有数据复制到新创建的记录集中让函数返回“真实”断开连接的记录集。如果相关,请告诉我,我会提供一些代码。

【讨论】:

  • +1 例如使用后关闭 RecordSet。不过,不确定有关摆脱这 3 行特定代码的建议。我同意删除disc.Close(),但如果我将其他两个sn-ps 留在原处,一切仍然有效。我宁愿过度清洁也不愿发生内存泄漏。
  • 很奇怪,VBScript 是一个真正的谜,那么在您将对象设置为空后它是否仍然有效。干杯! :)
  • 我很想看到将数据复制到新创建的记录集的代码!
【解决方案2】:

在您的函数中,如果您希望将记录集返回给调用进程,则无法关闭和清理记录集。

您可以清理任何连接和命令对象,但为了让您的记录集返回填充,您只需不要关闭它或丢弃它。

你的代码应该这样结束:

    'Cleanup
    discConn.Close()
    Set discConn = Nothing
    'discRS.Close()
    'Set discRs = Nothing
    'Set discCmd = Nothing
end function

【讨论】:

    【解决方案3】:

    在你的代码中我可以看到:

    Set .ActiveConnection = Nothing   ' Disconnect!
    

    那么,这个 Recordset 还没有关闭?

    【讨论】:

    • 不,Recordset 没有关闭,但已断开连接。我最好的猜测是Set GetDiscRS = discRS 可能是通过引用而不是创建副本来完成的;所以GetDiscRSdiscRS 都指向内存中的同一个对象。所以discRS.Close() 可能不仅会清空discRS,还会清空GetDiscRS 返回值。只是想知道为什么我找到的示例都关闭了函数中的记录集。
    【解决方案4】:

    他确实在使用断开连接的记录集。我开始在 VB6 中使用它们。你设置了 connection = Nothing 并且你基本上有一个集合类,其中包含记录集的所有方便方法(即排序、查找、过滤等....)。另外,您只在获取记录所需的时间内保持连接,所以当微软通过连接授权他们的服务器时,这是一个很好的方式来减少任何时候连接的用户数量。

    记录集功能齐全,只是没有连接到数据源。您可以重新连接它,然后应用对其所做的任何更改。

    很久以前,好像功能已经被删除了。

    【讨论】:

      【解决方案5】:

      您应该使用CursorLocation = adUseClient。然后您可以断开记录集。我创建了一个函数来将参数添加到命令字典对象,然后返回一个断开连接的记录集。

      Function CmdToGetDisconnectedRS(strSQL, dictParamTypes, dictParamValues)
      
                     'Declare our variables
                    Dim objConn
                     Dim objRS
                     Dim Query, Command
                     Dim ParamTypesDictionary, ParamValuesDictionary
      
      
                     'Open a connection
                     Set objConn = Server.CreateObject("ADODB.Connection")
                     Set objRS = Server.CreateObject("ADODB.Recordset") 
                     Set Command = Server.CreateObject("ADODB.Command")
                     Set ParamTypesDictionary = Server.CreateObject("Scripting.Dictionary")
                     Set ParamValuesDictionary = Server.CreateObject("Scripting.Dictionary")
                     Set ParamTypesDictionary = dictParamTypes
                     Set ParamValuesDictionary = dictParamValues
                     Query = strSQL
                     objConn.ConnectionString = strConn
                     objConn.Open
                     With Command
           .CommandText = Query
           .CommandType = adCmdText
           .CommandTimeout = 15
      
                     Dim okey
                     For Each okey in ParamValuesDictionary.Keys
                        .Parameters.Append .CreateParameter(CStr(okey), ParamTypesDictionary.Item(okey) ,adParamInput,50,ParamValuesDictionary.Item(okey))
                     Next
      
                      .ActiveConnection = objConn
                 End With
                     objRS.CursorLocation = adUseClient
                     objRS.Open Command , ,adOpenStatic, adLockBatchOptimistic
                     'Disconnect the Recordset
              Set objRS.ActiveConnection = Nothing
      
                     'Return the Recordset
                     Set CmdToGetDisconnectedRS = objRS     
      
                     'Clean up...
                     objConn.Close
                     Set objConn = Nothing
                     Set objRS = Nothing
                     Set ParamTypesDictionary =Nothing 
          Set ParamValuesDictionary =Nothing
          Set Command = Nothing
      End Function
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-24
        • 1970-01-01
        • 1970-01-01
        • 2011-06-01
        • 1970-01-01
        • 2010-12-12
        • 2011-04-19
        相关资源
        最近更新 更多