使用SQLDataReader对象时关闭SQLConnection对象的重要性

时间:2008-11-13 03:35:33

标签: vb.net generics ado.net sqlconnection.close

我目前的合约订婚是在一家大型电子商务公司。他们的代码库起源可以追溯到.Net 1.0,这让我感到惊讶,因为它包含了许多问题,这些问题提升了我所采取的最后废话之外的气味水平。

尽管如此并且试图将我的注意力分散开来,我还是愉快地尝试添加功能来修复其他问题或扩展更多废话。在我触摸DAL / BLL的时候,将完成上述操作所需的时间。然而,我希望得到专家的信任投票,以获得一些保证不浪费客户的时间,或者更糟糕的是通过触及“有效的东西”来降低我的可信度。当然,单元测试可以解决或至少减轻这种担忧。也许这也应该添加到wtf.com?

Public Function GetSizeInfoBySite(ByVal siteID As String) As IList
    Dim strSQL As String = "YES INLINE SQL!! :)"
    Dim ci As CrapInfo
    Dim alAnArrayList As ArrayList

    Dim cn As New SqlConnection(ConfigurationSettings.AppSettings("ConnectionString"))
    Dim cmd As New SqlCommand(strSQL, cn)
    cmd.Parameters.Add(New SqlParameter("@MySiteID", SqlDbType.NVarChar, 2)).Value = siteID
    cn.Open()
    Dim rs As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
    While rs.Read()
        ci = New CategoryInfo(rs("someID"), rs("someName"))
        If IsNothing(alAnArrayList) Then
            alAnArrayList = New ArrayList
        End If
        alAnArrayList.Add(ci)
    End While
    rs.Close()
    Return CType(alAnArrayList, IList)
End Function

有没有人看到这个问题,除了内联SQL,这让我的肠道流失?至少你不会通常将上面的内容包装在try / catch / finally中,我们大多数人都知道自.Net v1.0以来一直存在吗?更好的是,使用Using语句修复是否明智? SQLDataReader关闭是否真的自动封装了连接?

6 个答案:

答案 0 :(得分:4)

如果用户输入正确参数化,内联sql没有错,看起来就是这样。

除此之外,是的,你确实需要关闭连接。在一个繁忙的网站上,你可以达到极限,这将导致各种奇怪。

我也注意到它仍在使用arraylist。因为他们已经从.Net 1.0转移到了将它们更新为通用List<T>的时候(并且避免调用CType-你应该能够直接使用DirectCast())。

答案 1 :(得分:3)

绝对可以在Connection和Reader对象周围获取一些使用语句。如果存在异常,则在垃圾收集器到达它们之前不会关闭它们。

当有使用语句时,我倾向于不调用.Close()。即使SqlDataReader关闭了dispose上的连接(检查doco),在Connection周围使用也不会受到影响并且坚持使用模式。

如果你这样做,只有你需要在那里进行异常处理时才需要try / finally。我倾向于在更高级别保留异常处理(包装每个UI入口点,Library入口点,异常中的额外信息),因为stacktrace通常足以调试错误。

并不重要,但如果要重新分解,请将集合初始化移到循环外部。再想一想,如果没有记录,代码将返回null。

至少使用SqlParameters!如果你发现它(SQL注入攻击),无论多么好“清理”它,都要摆脱将用户输入与SQL连接起来的任何东西。

答案 2 :(得分:3)

当阅读器关闭时,连接将被关闭,因为它正在使用CloseConnection命令行为。

Dim rs As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)

根据MSDN(http://msdn.microsoft.com/en-us/library/aa326246(VS.71).aspx

  

如果在CommandBehavior设置为CloseConnection的情况下创建SqlDataReader,则关闭SqlDataReader会自动关闭连接。

答案 3 :(得分:1)

在回答乔尔和罗伯特所表达的一些重点时,我将以下方法重构为完美无缺。

Public Function GetSomeInfoByBusObject(ByVal SomeID As String) As IList
Dim strSQL As String = "InLine SQL"
Dim ci As BusObject
Dim list As New GenList(Of BusObject)
Dim cn As New SqlConnection(
    ConfigurationSettings.AppSettings("ConnectionString"))
Using cn
    Dim cmd As New SqlCommand(strSQL, cn)
    Using cmd
        cmd.Parameters.Add(New SqlParameter
            ("@SomeID", SqlDbType.NVarChar, 2)).Value = strSiteID
        cn.Open()
            Dim result As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
                While result.Read()
                    ci = New BusObject(rs("id), result("description"))
                    list.Add(DirectCast(ci, BusObject))
                End While
            result.Close()
        End Using
    Return list
End Using

结束功能

创建了一个很好的小助手类来包装通用的细节

Public Class GenList(Of T)
    Inherits CollectionBase
    Public Function Add(ByVal value As T) As Integer
        Return List.Add(value)
    End Function
    Public Sub Remove(ByVal value As T)
        List.Remove(value)
    End Sub
    Public ReadOnly Property Item(ByVal index As Integer) As T
        Get
            Return CType(List.Item(index), T)
        End Get
    End Property
End Class

答案 4 :(得分:0)

如果您使用的是c#,我会将datareader创建包装在using语句中,但我不认为vb有那些?

答案 5 :(得分:0)

Public Function GetSizeInfoBySite(ByVal siteID As String) As IList(Of CategoryInfo)
        Dim strSQL As String = "YES INLINE SQL!! :)"

        'reference the 2.0 System.Configuration, and add a connection string section to web.config
        '  <connectionStrings>
        '   <add name="somename" connectionString="someconnectionstring" />
        '  </connectionStrings >

        Using cn As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("somename").ConnectionString

            Using cmd As New SqlCommand(strSQL, cn)

                cmd.Parameters.Add(New SqlParameter("@MySiteID", SqlDbType.NVarChar, 2)).Value = siteID
                cn.Open()

                Using reader As IDataReader = cmd.ExecuteReader()

                    Dim records As IList(Of CategoryInfo) = New List(Of CategoryInfo)

                    'get ordinal col indexes
                    Dim ordinal_SomeId As Integer = reader.GetOrdinal("someID")
                    Dim ordinal_SomeName As Integer = reader.GetOrdinal("someName")

                    While reader.Read()
                        Dim ci As CategoryInfo = New CategoryInfo(reader.GetInt32(ordinal_SomeId), reader.GetString(ordinal_SomeName))
                        records.Add(ci)
                    End While

                    Return records

                End Using
            End Using
        End Using
    End Function

您可以尝试类似上面的内容,using语句将处理连接关闭和对象处理。当类实现IDisposable时,这是可用的。还要构建并返回CategoryInfo的IList。