在我的程序中,我有多个位置,我打开一个连接到Oracle数据库,通过存储过程读取一些行,它返回一个游标,将它们放入IDataReader,关闭连接然后继续。
现在一切正常,直到关闭连接。我已经看过通过TOAD for Oracle向数据库打开的连接,我发现,在我说m_Connection.Close
和m_Connection.Dispose
之后,数据库似乎保持连接打开。
我使用Oracle.DataAccess并在很短的时间后收到一个错误,即有很多连接。我对我的会话进行了调试,并确保vb执行close()命令并执行它,但数据库没有。任何人都知道如何解决这个问题?
答案 0 :(得分:1)
在.Net中,您需要在Try / Catch / Finally块中包装数据库连接,并始终关闭Finally部分中的连接。这有一个名为Using
块的简写。这意味着将连接保持为类的成员(正如您似乎正在做的那样)几乎总是错误的方法。 .Net已经过优化,因此最好为每个查询创建一个新的连接和命令对象。
DataReader有点特别:如果从使用块返回datareader,则可以在DataReader完成之前关闭连接。在C#中,我通常用迭代器解决问题(yield return)。由于VB.Net缺乏对此构造的支持,我可能会改为使用Action(Of IDataRecord)
,如下所示:
Public Sub MyOracleQuery(ByVal id As Integer, ByVal ProcessRecord As Action(Of IDataRecord))
Dim sql As String = "SELECT <columns> FROM MyTable WHERE ID= @Id"
Using cn As New OracleConnection("connection string"), _
cmd As New OracleCommand(sql, cn)
cmd.Parameters.Add("@Id", SqlDbTypes.Int).Value = id
cn.Open()
Using (rdr As IDataReader = cmd.ExecuteReader())
While rdr.Read()
ProcessRecord(rdr)
End While
End Using
End Using
End Sub
现在,您可以在调用它时将匿名方法传递给此代码:
Dim id As Integer
If Integer.TryParse(IDTextBox.Text, id) Then
MyOracleQuery(id, _
Function(r)
''#... Do something with each "r" here
End Function _
)
Else
''# Complain to user about invalid ID
End If
请注意,这需要Visual Studio 2010 /.Net 4用于多行匿名方法。对于较旧的平台,您需要声明方法。