我有以下代码执行查询并返回结果。但是,我环顾四周并找到一些例子来处理空值,但是我收到一个错误:“当没有数据存在时无效的读取尝试。”我也收到错误:“从'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
答案 0 :(得分:9)
我想提供另一个更高级的答案作为选项。许多类都可以在.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")
答案 1 :(得分:8)
您已经打开了阅读器,但没有要求它实际阅读任何内容。
这一行之后:
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