DataGridView选中记录批量删除过慢问题求助(附实现代码)
解决DataGridView批量删除速度慢的问题
你的代码现在速度慢主要是因为每次删除都单独打开/关闭数据库连接,并且单条执行DELETE语句,频繁的数据库往返和连接操作带来了大量开销。下面给你几个优化方向和具体的代码实现:
核心优化点
- 复用数据库连接,避免频繁打开关闭
- 批量执行删除操作,减少数据库往返次数
- 使用参数化查询,既防SQL注入又提升性能
优化后的删除按钮代码
private void delete_Click(object sender, EventArgs e) { // 收集所有选中的ID List<string> selectedIds = new List<string>(); foreach (DataGridViewRow item in advancedDataGridView1.Rows) { // 跳过DataGridView默认的空白新增行 if (item.IsNewRow) continue; bool isChecked = false; // 安全解析复选框值,避免空值报错 if (item.Cells[0].Value != null && bool.TryParse(item.Cells[0].Value.ToString(), out isChecked)) { if (isChecked) { string id = item.Cells[1].Value?.ToString(); if (!string.IsNullOrEmpty(id)) { selectedIds.Add(id); } } } } if (selectedIds.Count == 0) { MessageBox.Show("请先选择要删除的记录"); return; } // 批量删除逻辑 try { // 只打开一次数据库连接,避免频繁操作 conn.Open(); // 构建批量删除的SQL语句(适合ID数量不多的场景) string idsStr = string.Join("','", selectedIds); string sql = $"DELETE FROM tabl WHERE id IN ('{idsStr}')"; SqlCommand cmd = new SqlCommand(sql, conn); int affectedRows = cmd.ExecuteNonQuery(); // 删除后记得刷新DataGridView,建议调用你原来加载数据的方法,比如LoadData() advancedDataGridView1.Rows.Clear(); // LoadData(); MessageBox.Show($"成功删除 {affectedRows} 条记录"); } catch (Exception ex) { MessageBox.Show("删除失败:" + ex.Message); } finally { // 确保连接最终关闭,避免资源泄漏 if (conn.State == ConnectionState.Open) { conn.Close(); } } }
额外的小优化
1. 全选事件优化(跳过空白新行)
原来的全选代码会把DataGridView最后一行的空白新增行也选中,修改后更合理:
private void Chkselectall_CheckedChanged(object sender, EventArgs e) { foreach (DataGridViewRow row in advancedDataGridView1.Rows) { if (!row.IsNewRow) { row.Cells[0].Value = chkselectall.Checked; } } }
2. 异步操作避免UI卡顿
如果要删除的记录非常多,建议用异步操作防止界面冻结:
private async void delete_Click(object sender, EventArgs e) { // 收集选中ID的逻辑和上面一致... if (selectedIds.Count == 0) { MessageBox.Show("请先选择要删除的记录"); return; } // 禁用按钮防止重复点击 delete.Enabled = false; try { using (SqlConnection asyncConn = new SqlConnection(conn.ConnectionString)) { await asyncConn.OpenAsync(); string idsStr = string.Join("','", selectedIds); string sql = $"DELETE FROM tabl WHERE id IN ('{idsStr}')"; SqlCommand cmd = new SqlCommand(sql, asyncConn); int affectedRows = await cmd.ExecuteNonQueryAsync(); // 刷新数据 // LoadData(); MessageBox.Show($"成功删除 {affectedRows} 条记录"); } } catch (Exception ex) { MessageBox.Show("删除失败:" + ex.Message); } finally { delete.Enabled = true; } }
3. 参数化IN子句(彻底避免SQL注入)
如果ID是字符串类型,上面的IN写法存在SQL注入风险,更安全的方式是用参数数组:
// 构建参数化SQL string sql = "DELETE FROM tabl WHERE id IN ({0})"; List<SqlParameter> parameters = new List<SqlParameter>(); string[] paramNames = selectedIds.Select((id, index) => $"@id{index}").ToArray(); sql = string.Format(sql, string.Join(",", paramNames)); for (int i = 0; i < selectedIds.Count; i++) { parameters.Add(new SqlParameter($"@id{i}", selectedIds[i])); } SqlCommand cmd = new SqlCommand(sql, conn); cmd.Parameters.AddRange(parameters.ToArray()); int affectedRows = cmd.ExecuteNonQuery();
这种方式既能避免SQL注入,又能让数据库缓存执行计划,进一步提升性能。
内容的提问来源于stack exchange,提问作者user10888875




