DataGridView CellClick事件点击空值列报无法调用空值方法错误
报错根因
- 触发空值异常的核心原因:
RicercaEstrazioni字段配置为允许NULL,数据库返回的空值是DBNull.Value类型,和VB中的Nothing不是同一种类型,你写的两段代码都没有对该类型做校验,直接对空值对象调用GetString()、ToString()方法,就会抛出题目中的报错。 - 两段代码还存在其他会引发异常或逻辑错误的问题:
- 第一段数据库查询代码逻辑冗余:同一条SQL先后执行
ExecuteNonQuery、SqlDataAdapter填充DataTable、SqlDataReader读取三套操作,属于重复查询浪费性能;同时字符串拼接SQL存在注入风险,数据库连接未做自动释放,容易触发连接泄漏;除第8列外,其他字段只要存储了NULL值,直接调用GetDateTime()、GetString()这类强类型读取方法一样会报错。 - 第二段直接读取DataGridView行的代码存在列映射错误:
txtEstratto3读取了Estratto2列的值,txtEstratto4读取了Estratto3列的值,txtEstratto5读取了Estratto4列的值,最后还把Estratto5列的值赋给了txtEstratto1,运行后文本框加载的内容会完全错位。
- 第一段数据库查询代码逻辑冗余:同一条SQL先后执行
修复方案
优先选择直接读取DataGridView行的实现方案,无需每次点击都回库查询,响应速度更快、逻辑更简洁,修复后的完整代码如下:
Private Sub DataGridView1_CellClick(sender As Object, e As DataGridViewCellEventArgs) Handles DataGridView1.CellClick ' 点击列头、行头等无效区域时直接退出 If e.RowIndex < 0 Then Exit Sub Dim selectedRow As DataGridViewRow = DataGridView1.Rows(e.RowIndex) ' 封装通用空值安全读取方法,遇到DBNull/Nothing直接返回空字符串 Dim SafeGetText = Function(cellValue As Object) As String If cellValue Is DBNull.Value OrElse cellValue Is Nothing Then Return String.Empty End If Return cellValue.ToString() End Function ' 逐字段赋值,修正原代码的列映射错误 txtId.Text = SafeGetText(selectedRow.Cells("id").Value) ' 日期选择控件单独处理空值,避免类型转换异常 If TypeOf selectedRow.Cells("Data_Estraz").Value Is DateTime Then dtpDataEstrazione.Value = DirectCast(selectedRow.Cells("Data_Estraz").Value, DateTime) Else dtpDataEstrazione.Value = DateTime.Today End If txtRuota.Text = SafeGetText(selectedRow.Cells("Ruota").Value) txtEstratto1.Text = SafeGetText(selectedRow.Cells("Estratto1").Value) txtEstratto2.Text = SafeGetText(selectedRow.Cells("Estratto2").Value) txtEstratto3.Text = SafeGetText(selectedRow.Cells("Estratto3").Value) txtEstratto4.Text = SafeGetText(selectedRow.Cells("Estratto4").Value) txtEstratto5.Text = SafeGetText(selectedRow.Cells("Estratto5").Value) ' 核心修复:空值场景自动赋值空字符串,不会触发空值方法调用错误 txtRicercaEstrazioni.Text = SafeGetText(selectedRow.Cells("RicercaEstrazioni").Value) End Sub
如果你确实需要每次点击行都从数据库拉取最新数据(常规场景无必要,DataGridView绑定数据源时本身已经存储了全量行数据),需要注意两点:
- 删掉冗余的查询执行逻辑,只保留DataReader读取流程即可,用
Using块自动释放连接、命令、阅读器资源,改用参数化查询避免SQL注入 - 所有字段读取前必须调用
IsDBNull()做判断,不要直接调用强类型读取方法,比如第8列的读取逻辑要修改为:
' RicercaEstrazioni字段的安全读取写法 If dr.IsDBNull(8) Then txtRicercaEstrazioni.Text = String.Empty Else txtRicercaEstrazioni.Text = dr.GetString(8) End If
注意:只要是数据库中配置为允许NULL的字段,读取前必须做DBNull校验,这是ADO.NET数据读取的基础规则,跳过校验必然会在字段为空时抛出异常。
内容的提问来源于stack exchange,提问作者user19103492
相关产品推荐
相关产品推荐

