C# WinForm中DataGridView删除数据后SQL数据库未即时生效的问题求助
问题
开发C# Windows Form连接SQL数据库应用,DataGridView绑定数据库表后显示正常。点击删除按钮移除选中行后,数据库实际已删除该行(重启程序可见),但不重启程序的情况下(如注销重登),DataGridView仍会显示已删除的行。需要实现删除操作即时同步到数据库,且无需重启程序就能让DataGridView显示最新数据。
当前删除按钮代码:
private void btnDeleteUser_Click(object sender, EventArgs e) { string Username= dataGridView1[0,dataGridView1.SelectedCells[0].RowIndex].Value.ToString(); using (FrmLogin.connection1 = new SqlConnection(FrmLogin.conectionString)) using (SqlCommand sqlCommand1 = new SqlCommand("DELETE FROM Users Where UserName='" + Username + "' ", FrmLogin.connection1)) { FrmLogin.connection1.Open(); sqlCommand1.ExecuteNonQuery(); FrmLogin.connection1.Close(); MessageBox.Show("Deleted"); } dataGridView1.Rows.RemoveAt(dataGridView1.SelectedCells[0].RowIndex); }
相关截图:
- 首次运行截图:

- 删除行截图:

- 未重启程序注销重登后已删除行仍存在:

- 重启程序后已删除行消失:

解决方案
问题根源
- 仅手动移除了DataGridView的行,但注销重登时的数据源加载逻辑大概率使用了缓存的旧数据,而非重新从数据库拉取最新内容。
- 直接拼接字符串到SQL语句中,存在严重的SQL注入风险,必须立即修复。
1. 修复SQL注入,改用参数化查询
永远不要直接拼接用户输入到SQL语句,改用参数化查询确保安全:
private void btnDeleteUser_Click(object sender, EventArgs e) { // 先判断是否选中有效行 if (dataGridView1.SelectedRows.Count == 0) { MessageBox.Show("请选择要删除的用户行"); return; } var selectedRow = dataGridView1.SelectedRows[0]; string username = selectedRow.Cells[0].Value.ToString(); using (var conn = new SqlConnection(FrmLogin.conectionString)) { string deleteSql = "DELETE FROM Users WHERE UserName = @UserName"; using (var cmd = new SqlCommand(deleteSql, conn)) { // 添加参数,避免SQL注入 cmd.Parameters.AddWithValue("@UserName", username); conn.Open(); int affectedRows = cmd.ExecuteNonQuery(); if (affectedRows > 0) { MessageBox.Show("删除成功"); // 移除DataGridView中的选中行 dataGridView1.Rows.Remove(selectedRow); } else { MessageBox.Show("未找到对应用户,删除失败"); } } } }
2. 实现数据源刷新逻辑
注销重登后,必须重新从数据库查询最新数据,创建通用的加载用户列表方法:
private void LoadUserList() { // 清空DataGridView现有数据 dataGridView1.Rows.Clear(); using (var conn = new SqlConnection(FrmLogin.conectionString)) { string querySql = "SELECT * FROM Users"; using (var cmd = new SqlCommand(querySql, conn)) { conn.Open(); using (var reader = cmd.ExecuteReader()) { // 根据你的Users表结构,依次添加列数据 while (reader.Read()) { dataGridView1.Rows.Add( reader["UserName"].ToString(), reader["Password"].ToString(), // 示例列,根据实际表调整 reader["Role"].ToString() // 示例列,根据实际表调整 ); } } } } }
3. 在关键节点调用刷新方法
- 程序启动(如窗体
Load事件)时,调用LoadUserList()加载初始数据 - 删除操作成功后,若需要确保数据绝对同步,也可以直接调用
LoadUserList()替代手动移除行(更稳妥) - 注销重登成功后,立即调用
LoadUserList()重新加载最新用户数据
进阶优化:使用DataBinding简化同步
如果使用DataTable作为DataGridView的数据源,数据同步会更便捷:
private DataTable userDataTable; private void LoadUserList() { userDataTable = new DataTable(); using (var conn = new SqlConnection(FrmLogin.conectionString)) { string querySql = "SELECT * FROM Users"; using (var adapter = new SqlDataAdapter(querySql, conn)) { adapter.Fill(userDataTable); } } // 绑定数据源,后续DataTable更新会自动同步到DataGridView dataGridView1.DataSource = userDataTable; } // 删除操作后,重新加载DataTable即可自动同步显示 private void btnDeleteUser_Click(object sender, EventArgs e) { // ... 省略参数化删除代码 ... if (affectedRows > 0) { MessageBox.Show("删除成功"); // 重新加载最新数据,自动同步到DataGridView LoadUserList(); } }
这样无论删除操作后还是注销重登后,只要调用LoadUserList(),DataGridView就会显示数据库中的最新状态,不会再出现旧数据残留的问题。
内容的提问来源于stack exchange,提问作者mohammad
相关产品推荐
相关产品推荐

