You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动