基于DataGridView列查询数据库仅返回首行问题(VB.NET2015+SQL Server2014)
逐行搜索仅匹配首行的问题排查与修复
核心问题点
- 数据库资源未释放是仅返回首行结果的直接原因:循环内创建的
SqlConnection、SqlDataReader等数据库对象执行完查询后未做关闭、释放处理,第一次查询完成后连接始终处于占用状态,后续循环执行查询时会直接抛出连接相关异常,整个循环被Catch块捕获终止,只能保留第一行的查询结果。 - 结果存储逻辑存在缺陷:用于接收查询结果的
ID_code_Sathe5、ID_acckind、ID_ukolcode、ID_F_Takhsise_SatheTafzili_B_Moin均为单个字符串变量,每次读取记录时会直接覆盖变量内的历史值,即便所有查询正常执行,最终也只能留存最后一次查询的单条记录值,无法获取全量匹配结果。 NextResult()方法使用错误:该方法仅适用于读取单条命令返回的多个结果集(如一次执行多条SELECT语句的场景),当前逻辑为单条SELECT查询,外层嵌套Do ... Loop While rd.NextResult属于冗余逻辑,可能引发读取异常。- 存在无效判断与转换风险:
DataGridView1.Rows.Count <> 0判断放在循环内部会被重复执行,无实际意义;直接对row.Cells("انتخاب").Value做CBool转换时,遇到DataGridView新增空白行的DBNull值会直接抛出转换异常,导致循环提前中断。 - SQL拼接存在稳定性与安全隐患:通过字符串拼接组装查询条件,当单元格内容包含单引号等特殊字符时会触发SQL语法错误,同时存在SQL注入风险。
修复后参考代码
' 循环前统一判断是否存在待处理数据 If DataGridView1.Rows.Count = 0 Then MessageBox.Show("无待搜索数据") Return End If ' 用DataTable存储全量匹配结果,避免单值变量覆盖问题 Dim resultTable As New DataTable() resultTable.Columns.Add("ID", GetType(String)) resultTable.Columns.Add("Acckind", GetType(String)) resultTable.Columns.Add("UkolCode", GetType(String)) resultTable.Columns.Add("Code_Sathe5", GetType(String)) ' 可根据业务需要追加其他存储字段 Dim connStr As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString Try For i As Integer = 0 To DataGridView1.Rows.Count - 1 Dim row As DataGridViewRow = DataGridView1.Rows(i) ' 跳过DataGridView自带的新增空白行 If row.IsNewRow Then Continue For ' 安全判断选中状态,避免DBNull转换报错 Dim isSelected As Boolean = False If row.Cells("انتخاب").Value IsNot DBNull.Value Then isSelected = CBool(row.Cells("انتخاب").Value) End If If Not isSelected Then Continue For ' 读取搜索关键词,处理空值 Dim searchName As String = "" If row.Cells(8).Value IsNot DBNull.Value Then searchName = row.Cells(8).Value.ToString().Trim() End If If String.IsNullOrEmpty(searchName) Then Continue For ' Using块会自动释放连接、命令、读取器资源,无需手动调用Close/Dispose Using con As New SqlConnection(connStr) Using cmd As New SqlCommand() cmd.Connection = con ' 用参数化查询替代字符串拼接,避免语法错误与注入风险 cmd.CommandText = "SELECT ID,Acckind,UkolCode,Code_Sathe5 FROM F_Takhsise_SatheTafzili_B_Moin WHERE name = @SearchName" ' 参数长度可根据数据库字段实际长度调整 cmd.Parameters.AddWithValue("@SearchName", searchName) con.Open() Using rd As SqlDataReader = cmd.ExecuteReader() ' 单SELECT语句仅返回一个结果集,无需调用NextResult While rd.Read() Dim newRow As DataRow = resultTable.NewRow() newRow("ID") = rd("id").ToString() newRow("Acckind") = rd("acckind").ToString() newRow("UkolCode") = rd("ukolcode").ToString() newRow("Code_Sathe5") = rd("code_Sathe5").ToString() resultTable.Rows.Add(newRow) End While End Using End Using End Using Next ' 循环执行完成后,resultTable内存储了所有匹配结果,可直接绑定控件或遍历处理 ' 示例:DataGridView2.DataSource = resultTable Catch ex As Exception MessageBox.Show(ex.ToString()) End Try
内容的提问来源于stack exchange,提问作者kushimkoosh
相关产品推荐
相关产品推荐

