如何正确展示数据?DataGridView联动查询空值及行数据异常求助
解决DataGridView查询的空值报错与结果覆盖问题
先拆解你代码里的核心问题:
- 空值报错:当
row.Cells[4].Value为null或DBNull时,直接调用ToString()会触发空引用异常; - 仅显示单条结果:你在循环里每次都重新创建
DataTable并覆盖dgvSign.DataSource,最终只会保留最后一次查询的数据(你提到仅显示第一行,大概率是循环提前终止或后续行查询未执行,但本质是数据源被重复覆盖)。
另外还有两个隐藏问题:每次循环频繁开关数据库连接会损耗性能,字符串拼接SQL语句存在SQL注入风险,这是必须修复的安全隐患。
下面是修正后的完整代码,我会逐一标注改进点:
// 用using语句自动管理连接、命令、适配器,避免手动关闭的遗漏 using (SqlConnection ss = new SqlConnection(yourConnectionString)) // 替换成你的数据库连接字符串 { ss.Open(); // 初始化一个空表,用来存储所有查询结果 DataTable resultDt = new DataTable(); foreach (DataGridViewRow row in dgvAtt.Rows) { // 跳过DataGridView默认的空行,以及单元格值为空的行 if (row.IsNewRow || row.Cells[4].Value == null || row.Cells[4].Value == DBNull.Value) { continue; } string nameValue = row.Cells[4].Value.ToString().Trim(); // 额外处理空白字符串的情况 if (string.IsNullOrEmpty(nameValue)) { continue; } // 使用参数化查询,彻底规避SQL注入风险 string query = "SELECT Signature FROM TBL_Student WHERE Name = @StudentName"; using (SqlCommand cmd = new SqlCommand(query, ss)) { cmd.Parameters.AddWithValue("@StudentName", nameValue); // 每次查询的结果存入临时表,再合并到总结果表中 using (SqlDataAdapter dp = new SqlDataAdapter(cmd)) { DataTable tempDt = new DataTable(); dp.Fill(tempDt); resultDt.Merge(tempDt); } } } // 所有查询完成后,一次性绑定数据源 dgvSign.DataSource = resultDt; }
关键改进说明:
- 空值拦截:通过
row.IsNewRow跳过DataGridView自带的空行,同时检查单元格值是否为null/DBNull,还处理了空白字符串场景; - 避免结果覆盖:创建总结果表
resultDt,每次查询的临时表合并进去,最后一次性设置数据源; - 资源自动管理:用
using语句自动释放连接、命令等资源,无需手动调用Close(),且仅打开一次连接提升性能; - SQL注入防护:用参数
@StudentName替代字符串拼接,确保输入的特殊字符不会破坏SQL语句结构; - 移除冗余代码:删掉了无用的
ExecuteNonQuery(),这个方法仅用于执行增删改语句,查询场景不需要调用。
如果需要去重的查询结果,可以在SQL语句中添加DISTINCT:
SELECT DISTINCT Signature FROM TBL_Student WHERE Name = @StudentName
内容的提问来源于stack exchange,提问作者Diether Noche
相关产品推荐
相关产品推荐

