You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决GetStudentResultTotal函数DBNull转Double无效的空值处理问题

解决SUM查询返回Null引发的类型转换错误

问题描述

我编写的GetStudentResultTotal函数用于对StudentData.tblStudentResult表的Total列求和并返回结果,但首次插入记录时,若查询返回Null值,会抛出‘Conversion from type dbnull to type double is not valid’错误,请问该如何控制空值?

相关代码

Function 1: GetStudentResultTotal

Function GetStudentResultTotal(ByVal schid As String, ByVal level As String, ByVal session As String, ByVal term As String, ByVal klass As String, ByVal regno As String) As Double
        If SCH_ID <> "" Then
            schid = SCH_ID
        End If
        Dim total As Double = 0
        Dim subjectCount As Integer = 0
        Dim fields As New ArrayList
        fields.Add("SUM(" & StudentData.Total & ") AS GrandTotal")
        Dim filterValues As New Hashtable
        filterValues.Add(StudentData.SchoolID, schid)
        filterValues.Add(StudentData.Level, level)
        filterValues.Add(StudentData.Session, session)
        filterValues.Add(StudentData.Term, term)
        filterValues.Add(StudentData.Klass, klass)
        filterValues.Add(StudentData.RegNo, regno)
        Dim filterArgs As String = "WHERE " & StudentData.SchoolID & "=@" & StudentData.SchoolID & " AND " & StudentData.Level & "=@" & StudentData.Level & " AND " & StudentData.Session & "=@" & StudentData.Session & " AND " & StudentData.Term & "=@" & StudentData.Term & " AND " & StudentData.Klass & "=@" & StudentData.Klass & " AND " & StudentData.RegNo & "=@" & StudentData.RegNo
        Dim data As DataSet = _Data.GetData(StudentData.tblStudentResult, fields, filterValues, filterArgs)
        'If data.Tables(0).Rows.Count > 0 Then
        '    For Each dr As DataRow In data.Tables(0).Rows
        '        total += CDbl(NormalizeRecord(dr(StudentData.Total)))
        '        subjectCount += 1
        '    Next
        'End If
        Dim dr As DataRow = data.Tables(0).Rows(0)
        total = CDbl(dr("GrandTotal"))
        Return total
End Function

Function 2: GetData

Function GetData(ByVal tbl As String, ByVal values As ArrayList, ByVal filters As Hashtable, ByVal filterArgs As String) As DataSet
        Dim _ds As New DataSet
        Dim sql As String = "SELECT "
        Dim fields As String = ""
        Using conn As New MySqlConnection(connString)
            conn.Open()
            If values IsNot Nothing Then
                For i = 0 To values.Count - 1
                    If fields = "" Then
                        fields = values.Item(i).ToString
                    Else
                        fields &= "," & values.Item(i).ToString
                    End If
                Next
                sql &= fields & " "
            End If
            sql &= "FROM " & tbl
            If filterArgs <> "" Then
                sql &= " " & filterArgs
            End If
            Dim cmd As New MySqlCommand(sql, conn)
            If filters IsNot Nothing Then
                For i = 0 To filters.Count - 1
                    cmd.Parameters.AddWithValue("@" & filters.Keys(i), filters.Values(i))
                Next
            End If
            Dim da As New MySqlDataAdapter(cmd)
            da.Fill(_ds)
            conn.Close()
        End Using
        Return _ds
End Function

Function 3: NormalizeRecord

Function NormalizeRecord(ByVal value As String) As String
        If value = "-" Then
            value = "0"
        End If
        Return value
End Function

解决方案

有三种可靠的方式处理这个空值问题,按推荐程度排序:

1. 在SQL层面处理Null(推荐)

直接在MySQL的SUM函数中使用IFNULL,将Null值转为0,这样查询结果永远不会返回Null,从根源避免转换错误。修改fields.Add的语句:

fields.Add("SUM(IFNULL(" & StudentData.Total & ", 0)) AS GrandTotal")

这种方法的优势是把空值处理放在数据库层,后续代码无需额外判断,逻辑更简洁可靠。

2. 在代码中显式判断DBNull

如果无法修改SQL,可以在获取DataRow后,先判断字段是否为DBNull,再执行类型转换:

Dim dr As DataRow = data.Tables(0).Rows(0)
If Not IsDBNull(dr("GrandTotal")) Then
    total = CDbl(dr("GrandTotal"))
Else
    total = 0.0
End If

3. 复用NormalizeRecord函数优化

可以扩展现有NormalizeRecord逻辑,或者在转换前结合空值判断:

Dim grandTotalValue As Object = dr("GrandTotal")
total = CDbl(If(IsDBNull(grandTotalValue), 0, NormalizeRecord(grandTotalValue.ToString())))

这种方式适合需要统一处理特殊值(比如原函数中的"-"转0)的场景。

修改后的完整函数示例(方法1)

Function GetStudentResultTotal(ByVal schid As String, ByVal level As String, ByVal session As String, ByVal term As String, ByVal klass As String, ByVal regno As String) As Double
    If SCH_ID <> "" Then
        schid = SCH_ID
    End If
    Dim total As Double = 0
    Dim fields As New ArrayList
    ' 使用IFNULL确保SUM结果不为Null
    fields.Add("SUM(IFNULL(" & StudentData.Total & ", 0)) AS GrandTotal")
    Dim filterValues As New Hashtable
    filterValues.Add(StudentData.SchoolID, schid)
    filterValues.Add(StudentData.Level, level)
    filterValues.Add(StudentData.Session, session)
    filterValues.Add(StudentData.Term, term)
    filterValues.Add(StudentData.Klass, klass)
    filterValues.Add(StudentData.RegNo, regno)
    Dim filterArgs As String = "WHERE " & StudentData.SchoolID & "=@" & StudentData.SchoolID & " AND " & StudentData.Level & "=@" & StudentData.Level & " AND " & StudentData.Session & "=@" & StudentData.Session & " AND " & StudentData.Term & "=@" & StudentData.Term & " AND " & StudentData.Klass & "=@" & StudentData.Klass & " AND " & StudentData.RegNo & "=@" & StudentData.RegNo
    Dim data As DataSet = _Data.GetData(StudentData.tblStudentResult, fields, filterValues, filterArgs)
    Dim dr As DataRow = data.Tables(0).Rows(0)
    total = CDbl(dr("GrandTotal"))
    Return total
End Function

内容的提问来源于stack exchange,提问作者Fabian Technology

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 06:45:46