我有以下执行查询并返回结果的代码。然而,我环顾四周,发现了一些处理null值的例子,但我得到了一个错误:"当没有数据时,读取的尝试无效。"我还得到了错误:"从类型'DBNull'转换为类型'Decimal'是无效的。">
有人能帮我解决这个代码,防止空值破坏我的程序吗?
Private Sub EFFICIENCY_STACKRANK_YTD(ByVal EMPLOYEE As String)
Dim queryString As String = "SELECT " & _
" (SELECT CAST(SUM(TARGET_SECONDS) AS DECIMAL)/ CAST(SUM(ROUTE_SECONDS) AS DECIMAL) FROM dbo.APE_BUSDRIVER_MAIN WITH(NOLOCK) WHERE APE_AREA_OBJID = " & lblAreaOBJID.Text & " AND EMPLOYEE_NAME = '" & EMPLOYEE & "' AND YEAR_TIME = '" & cbYear.Text & "' AND ACTIVE = 1) AS RESULT1" & _
" FROM dbo.APE_BUSDRIVER_MAIN "
Using connection As New SqlConnection(SQLConnectionStr)
Dim command As New SqlCommand(queryString, connection)
connection.Open()
Dim reader As SqlDataReader = command.ExecuteReader()
If reader.Read Then
RESULT1 = reader("RESULT1")
Else
RESULT1 = 0
End If
End Using
End Sub
您打开了阅读器,但没有要求它实际读取任何内容。
此行之后:
Dim reader As SqlDataReader = command.ExecuteReader()
添加
If reader.Read() Then
并将读取的结果包装到这个if语句中,即
If reader.Read() Then
Dim index As Integer = reader.GetOrdinal("RESULT1")
If reader.IsDBNull(index) Then
RESULT1 = String.Empty
Else
RESULT1 = reader(index)
End If
End If
请注意,这是有效的,因为SQL应该只返回一条记录。如果您正在读取多条记录,则需要在循环中调用Read语句,直到没有更多记录为止,即
Do While reader.Read()
Loop
我想提供另一个更高级的答案作为选项。许多类可以像这样在.NET中进行扩展。
如果您在应用程序中定期执行这样的"Is NULL"检查,则可以选择扩展DataReader类一次,以便在应用程序的任何位置都可以使用其他函数。下面是一个在数据读取器类上创建名为"ReadNullAsString()"的扩展的示例。这使得函数在遇到DbNull时总是返回String.Empty。
第1部分,如果应用程序是一个网站,请将此模块代码放在App_code中的一个新类文件中,否则请放在您喜欢的位置。有两个重载,一个用于字段的序号位置(也称为索引),另一个用于该字段的ColumnName。
Public Module DataReaderExtensions
''' <summary>
''' Reads fieldName from Data Reader. If fieldName is DbNull, returns String.Empty.
''' </summary>
''' <returns>Safely returns a string. No need to check for DbNull.</returns>
<System.Runtime.CompilerServices.Extension()> _
Public Function ReadNullAsEmptyString(ByVal reader As IDataReader, ByVal fieldName As String) As String
If IsDBNull(reader(fieldName)) Then
Return String.Empty
Else
Return reader(fieldName)
End If
Return False
End Function
''' <summary>
''' Reads fieldOrdinal from Data Reader. If fieldOrdinal is DbNull, returns String.Empty.
''' </summary>
''' <returns>Safely returns a string. No need to check for DbNull.</returns>
<System.Runtime.CompilerServices.Extension()> _
Public Function ReadString(ByVal reader As IDataReader, ByVal fieldOrdinal As Integer) As String
If IsDBNull(reader(fieldOrdinal)) Then
Return ""
Else
Return reader(fieldOrdinal)
End If
Return False
End Function
End Module
步骤2,这样调用新的扩展:
' no need to check for DbNull now, this functionality is encapsulated in the extension module.
RESULT1 = reader.ReadNullAsEmptyString(index)
'or
RESULT1 = reader.ReadNullAsEmptyString("RESULT1")