我有一个在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文章缺少的实际使用示例。)
答案 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的部分。