【问题标题】:Function Return Issue?函数返回问题?
【发布时间】:2014-02-17 16:21:28
【问题描述】:

在我的 VB.Net 程序中,我发现两 (2) 个警告显示以下消息:

函数不会在所有代码路径上返回值。使用结果时可能会在运行时发生空引用异常

帮助我解决问题所在。以下快照是警告错误指示的位置:

“结束功能”附近的第一个警告

'Executes SQL commands to the system database
Public Function ExecSQL(ByVal sql As String)
        Dim com As New MySqlCommand(sql)
        Try
            RefreshConnection()
            com.Connection = con
            com.ExecuteNonQuery()
        Catch ex As Exception
            Return ex
            MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
        End Try
End Function

'End Function' 附近的第二次 Waring

'Get the value of an specific field in a given sql string
    Public Function GetField(ByVal sql As String, ByVal field As String)
        Try
            RefreshConnection()
            Dim com As New MySqlCommand(sql, con)
            Dim dReader As MySqlDataReader = com.ExecuteReader

            While dReader.Read
                GetField = dReader(field).ToString
            End While
            dReader.Close()
        Catch ex As Exception
            Return ex
            MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
        End Try
    End Function

【问题讨论】:

  • 这段代码在一个与您的问题无关的重要方面存在缺陷:它迫使您以极易受到 sql 注入攻击的方式构建 sql 查询。 它实际上是在乞求被黑。
  • 另外:单个共享连接在 .Net 中不是最优的。相反,.Net 依赖于一种称为连接池的功能,因此在大多数情况下,您应该为每次调用数据库使用一个新的连接对象。真的。相反,只需保留一个共享连接 string 以方便创建连接。
  • 哦,打开 Option Strict!

标签: vb.net visual-studio-2010 .net-4.0


【解决方案1】:

这是因为在异常处理程序中您实际上返回了异常对象ex。如果没有发生异常,您不会返回任何内容。您可以在 Catch ex as Exception 上方显式添加 Return Nothing,但我猜从消息​​中 VB 会自动为您执行此操作...

顺便说一句:将异常返回给调用者有什么意义?将消息框放入调用方法并将您的调用包装在Try-Catch 中。显然不应该与用户交互的方法根本不应该显示消息。然后您可以将异常向上传递,直到您结束表示层。

长话短说:业务逻辑中没有消息框。仅在表示层中的用户信息。


阅读您的第二种方法后:这里的情况更糟!如果数据读取器有行,则将该方法的结果设置为您找到的最后一个 (!) 结果(这本身就是一个 WTF,但又是另一回事)。如果发生错误,结果是Exception类型的对象,所以调用代码甚至需要确定函数调用的结果到底是字段值还是异常!

我的朋友,这真是糟糕的设计。


您要求提供固定代码:

'Executes SQL commands to the system database
Public Sub ExecSQL(ByVal sql As String)
    Dim com As New MySqlCommand(sql)

    RefreshConnection()
    com.Connection = con
    com.ExecuteNonQuery()
End Sub

'Get the value of an specific field in a given sql string
Public Function GetField(ByVal sql As String, ByVal field As String)
    RefreshConnection()
    Dim com As New MySqlCommand(sql, con)
    Dim dReader As MySqlDataReader = com.ExecuteReader

    GetField = Nothing

    While dReader.Read
        GetField = dReader(field).ToString
    End While
    dReader.Close()
End Function

【讨论】:

  • 不,因为那会使我的回答无效。我可以在我的回答中给你一个例子。
  • 所以我已经修复了你的代码。请注意,现在调用者必须处理异常。您应该真的花一分钟时间思考拥有While dReader.Read 是否正确。如果从数据库中读取多于一行会怎样?
  • 是的,你是对的。你的更正是有效的。但是第二个函数 GetField steel 有警告错误。
  • 我稍微编辑了第二个,以便在阅读器没有行的情况下返回Nothing
【解决方案2】:

这里有几个缺陷。为简洁起见,我将发布一些改进的代码:

'Executes SQL commands to the system database
Private Function ExecSQL(ByVal sql As String, ByVal params As IEnumerable(Of MySqlParameter))
    Using cn As New MySqlConnection(GetConnectionString()), _
          com As New MySqlCommand(sql, cn)

        For Each param As MySqlParameter in params
           com.Parameters.Add(param)
        Next param
        cn.Open()
        com.ExecuteNonQuery()
    End Using
End Function

'Get the value of an specific field in a given sql string
Private Function GetField(Of T)(ByVal sql As String, ByVal params As IEnumerable(Of MySqlParameter), ByVal field As String) As T
     Using cn As New MySqlConnection(GetConnectionString())
           com As New MySqlCommand(sql, cn)

         For Each param As MySqlParameter In params
            com.Parameters.Add(param)
         Next param
         cn.Open()

         Using rdr As MySqlDataReader = com.ExecuteReader()
             While rdr.Read()
                 Return CType(rdr(field), T)
             End While
         End Using
    End Using
    Return Nothing
End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-02
    • 2016-01-08
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 2011-10-05
    • 2020-09-09
    相关资源
    最近更新 更多