0

我目前的合同约定是在一家大型电子商务公司工作。他们的代码库起源于 .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 之外,还有人看到这个问题吗?至少您通常不会将上述内容包装在我们大多数人都知道自 .Net v1.0 以来一直存在的 try/catch/finally 中?更好的是用 Using 语句修复不是明智的吗?SQLDataReader close 是否真的封装了自动关闭的连接?

4

6 回答 6

4

如果用户输入被正确参数化,则内联 sql 没有任何问题,看起来就是这样。

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

我还注意到它仍在使用数组列表。由于他们已经从 .Net 1.0 继续前进,是时候将它们更新为 genericList<T>了(并避免调用 CType——你应该能够改为使用 DirectCast() )。

于 2008-11-13T03:53:16.833 回答
3

肯定会得到一些关于 Connection 和 Reader 对象的 using 语句。如果有异常,它们不会被关闭,直到垃圾收集器找到它们。

当有 using 语句时,我倾向于不调用 .Close() 。即使 SqlDataReader 在 dispose 时关闭连接(检查文档),在 Connection 周围放置 using 也不会伤害并坚持模式。

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

这并不重要,但如果您正在重构,请将集合初始化移到循环之外。再三考虑,如果没有记录,代码将返回 null。

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

于 2008-11-13T03:48:32.927 回答
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 会自动关闭连接。

于 2008-11-13T04:18:48.060 回答
1

为了回应 Joel 和 Robert 指出的一些重要观点,我将方法重构如下,它运行完美。

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
于 2008-11-13T15:15:28.137 回答
0

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

于 2008-11-13T03:48:50.023 回答
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。

于 2009-05-20T01:54:46.143 回答