C#报错无法将DBNull对象转换为其他类型 求排查修复方案
错误原因
- 核心触发原因:读取数据库字段时未做DBNull判断。数据库中字段存NULL值时,
SqlDataReader读取到的结果是DBNull.Value类型,该类型无法直接通过Convert.ToInt32转换为int,直接调用转换就会抛出「对象无法从DBNull转换为其他类型」异常。 - 隐藏语法错误:操作
Stotal_table的UPDATE语句多写了一个多余逗号,语句为Update Stotal_table set MiniBar=@MiniBar, where Item=@Item,执行时会触发SQL语法错误。 - 资源泄漏风险:
SqlConnection、SqlCommand等数据库对象未做资源自动释放处理,若执行过程中抛出异常,数据库连接不会被主动关闭,会持续占用连接池资源。 - 前置校验缺失:未判断
cbox2.SelectedItem是否为空,若下拉框无选中项直接调用ToString()会触发空引用异常;定义的连接字符串变量未实际使用,存在冗余代码。 - 规范问题:直接在master系统库中创建业务表,master是SQL Server存储系统元数据、配置信息的系统库,不适合存放业务数据。
修复方案
- 所有从
SqlDataReader读取的字段,先判断是否为DBNull.Value,如果是NULL值则赋默认值0,再做类型转换。 - 删掉UPDATE语句中SET子句末尾多余的逗号,修正SQL语法。
- 所有数据库操作对象用
using块包裹,执行结束后自动释放资源,无需手动调用Close(),异常场景下也能安全释放连接。 - 增加前置入参校验,操作前先确认下拉框选中项、数值输入值合法;抽离重复的连接创建逻辑,删除冗余代码。
- 建议后续单独创建业务数据库存放两张业务表,不要占用master系统库。
修复后完整代码
// 前置入参校验 if (cbox2.SelectedItem == null) { MessageBox.Show("请先选择对应物料项"); return; } int addQty = (int)Nd2.Value; string connStr = @"Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=master;Integrated Security=True;Application Name=Aung"; // 处理Mini_table表逻辑 using (SqlConnection connection = new SqlConnection(connStr)) { connection.Open(); SqlCommand cmdCount = new SqlCommand("SELECT COUNT(*) FROM Mini_table WHERE Item = @Item", connection); cmdCount.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); int count = (int)cmdCount.ExecuteScalar(); int currentQty = 0; if (count > 0) { SqlCommand command = new SqlCommand("SELECT Qty FROM Mini_table WHERE Item = @Item", connection); command.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { // 核心修复:判断DBNull后再转换 currentQty = reader["Qty"] == DBNull.Value ? 0 : Convert.ToInt32(reader["Qty"]); } } SqlCommand updatecmd = new SqlCommand("Update Mini_table set Qty=@Qty, Date=@Date where Item=@Item", connection); updatecmd.Parameters.AddWithValue("@Qty", currentQty + addQty); updatecmd.Parameters.AddWithValue("@Date", DateTime.Now); updatecmd.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); updatecmd.ExecuteNonQuery(); dgv2.DataSource = null; MessageBox.Show("Update successfully"); } else { SqlCommand insertcmd = new SqlCommand("insert into Mini_table(Item,Qty,Date)values(@Item,@Qty,@Date)", connection); insertcmd.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); insertcmd.Parameters.AddWithValue("@Qty", addQty); insertcmd.Parameters.AddWithValue("@Date", DateTime.Now); insertcmd.ExecuteNonQuery(); dgv2.DataSource = null; MessageBox.Show("Insert successfully"); } } // 处理Stotal_table表逻辑 using (SqlConnection connection = new SqlConnection(connStr)) { connection.Open(); SqlCommand cmdCount = new SqlCommand("SELECT COUNT(*) FROM Stotal_table WHERE Item = @Item", connection); cmdCount.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); int count = (int)cmdCount.ExecuteScalar(); int currentMiniBar = 0; if (count > 0) { SqlCommand command = new SqlCommand("SELECT MiniBar FROM Stotal_table WHERE Item = @Item", connection); command.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); using (SqlDataReader reader = command.ExecuteReader()) { while (reader.Read()) { // 核心修复:判断DBNull后再转换 currentMiniBar = reader["MiniBar"] == DBNull.Value ? 0 : Convert.ToInt32(reader["MiniBar"]); } } // 修复:删除@MiniBar后多余的逗号 SqlCommand updatecmd = new SqlCommand("Update Stotal_table set MiniBar=@MiniBar where Item=@Item", connection); updatecmd.Parameters.AddWithValue("@MiniBar", currentMiniBar + addQty); updatecmd.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); updatecmd.ExecuteNonQuery(); } else { SqlCommand insertcmd = new SqlCommand("insert into Stotal_table(Item,MiniBar)values(@Item,@MiniBar)", connection); insertcmd.Parameters.AddWithValue("@Item", cbox2.SelectedItem.ToString()); insertcmd.Parameters.AddWithValue("@MiniBar", addQty); insertcmd.ExecuteNonQuery(); } }
内容的提问来源于stack exchange,提问作者Aung
相关产品推荐
相关产品推荐

