经典ASP VBScript需要替换MyConn.Execute(查询)

时间:2017-07-14 14:23:39

标签: mysql vbscript asp-classic garbage-collection

我有一个在ASP VBScript上运行的站点,原始代码永远不会关闭数据库连接。它打开连接作为任何给定页面的“启动”的一部分,然后执行它做的任何事情并停止 - 但从不显式关闭连接。现在这会引起Web服务器级别崩溃的问题 - 可能是因为缺少垃圾收集。

所以我想创建一个函数,作为整个站点中所有MyConn.Execute(sqlQuery)命令的替代品。我找到了一些很好的候选人,但似乎没有一个能够奏效。最有希望的似乎是下面的代码,但当我尝试实际使用记录集返回时,我得到一个错误。

Function GetRS(strSQL)
  'this function returns a disconnected RS

  'Set some constants
  Const adOpenStatic = 3    
  Const adUseClient = 3
  Const adLockBatchOptimistic = 4 

  'Declare our variables
  Dim oConn
  Dim strSQL
  Dim oRS

  'Open a connection
  Set oConn = Server.CreateObject("ADODB.Connection")
  oConn.ConnectionString = "Driver={MySQL ODBC 5.3 Unicode Driver};Server=localhost;User=foo;Password=bar;Database=baz"
  oConn.Open

  'Create the Recordset object
  Set oRS = Server.CreateObject("ADODB.Recordset")
  oRS.CursorLocation = adUseClient

  'Populate the Recordset object with a SQL query
  oRS.Open strSQL, oConn, adOpenStatic, adLockBatchOptimistic

  'Disconnect the Recordset
  Set oRS.ActiveConnection = Nothing

  'Return the Recordset
  Set GetRS = oRS

  'Clean up...
  oConn.Close
  oRS.Close
  Set oConn = Nothing
  Set oRS = Nothing
End Function

'call the function
strSQL = "SELECT * FROM Authors"   
set RS = GetRS(strSQL)

(来源:http://www.4guysfromrolla.com/webtech/080101-1.shtml

这是我的测试代码:

Set rs = GetRS( "SELECT `first_name` FROM `users` WHERE `id`=123" )
x = rs( "first_name" )
response.write x

我收到错误:

ADODB.Recordset error '800a0cc1'

Item cannot be found in the collection corresponding to the requested name or ordinal.

/test.asp, line 25 

使用序数 - rs(0) - 返回相同的错误。

对我来说看起来像一个空的记录集,但它是一个合法的Query,它确实会返回一条记录。

有谁知道为什么这不起作用,或者可以指向其他可以完成这项工作的代码? (特别是4guys文章缺少的实际使用示例。)

1 个答案:

答案 0 :(得分:0)

我的理解是Recordset与数据源绑定。当您执行查询时,默认情况下,客户端(您的程序)不会获取查询的全部内容,但会等到您实际请求数据。这样,您可以选择特定的页面大小,页面偏移量等,以便有效地从数据库中选择行,而无需通过网络传输数百万行。

作为此的副作用,如果关闭数据库连接,将无法再使用Recordset。在完成连接之前,必须保持连接处于打开状态。以同样的方式,关闭Recordset本身将阻止您进一步与其进行交互。

您有两种选择:在关闭之前将数据从Recordset复制到您自己的变量/数组中,或使用不同的技术来管理您的连接。我将在这里讨论后一种选择。

有一种技术可以让你打开一次数据库连接,并确保它在终止时被VBScript正确关闭。

Class DbConnectionManager
    Private Sub Class_Initialize()
        Set oConn = Server.CreateObject("ADODB.Connection")
        oConn.ConnectionString = "Driver={MySQL ODBC 5.3 Unicode Driver};Server=localhost;User=foo;Password=bar;Database=baz"
        oConn.Open
    End Sub

    Private Sub Class_Terminate()
        oConn.Close
    End Sub
End Class

Dim connMgr : Set connMgr = New DbConnectionManager

此代码段未经测试,但一般原则是您通过定义类并创建其实例来启动程序。创建类实例时,将调用Class_Initialize,当程序结束(或实例被删除并进行垃圾收集)时,将调用Class_Terminate。这意味着在程序结束之前应始终调用oConn.Close,即使出现错误也是如此。

这是类如何工作的一个非常基本的示例,但您实际上可以进一步扩展该类并将您的Execute函数插入到类本身中以封装数据库连接详细信息以便于维护。如果您还没有在VBScript中使用过类,但是您对面向对象编程的工作方式有基本的了解,我强烈建议您尝试使用。

额外奖励:看起来你正在传递原始SQL字符串。为避免SQL注入漏洞,请不要动态构建SQL查询。相反,请使用ADO和参数,以便可以安全地将任何用户创建的内容传递到查询中,而不会带来安全风险。 How do I run a parameterized SQL query in classic ASP? And is it secure? W3School还有一个关于如何使用ADO的部分。