修改数据库位置名称后产品表未同步?C#代码问题排查
数据库位置名称批量更新问题排查与修复
问题背景
我有两个数据库表:
- dbLocation:仅包含存储物理位置的
loc_name列,已关联至下拉菜单 - DB_Main:存储全量产品信息,包含
Location列
需求是修改dbLocation表中的位置名称,同时自动更新DB_Main表中所有对应位置的产品的Location字段。但执行现有代码后,dbLocation表中旧位置仍保留,仅新增了新位置,DB_Main表无任何变化。其中NameLabel显示当前位置名称(来自上一表单),textbox用于输入新位置名称,现有C#代码如下:
private void Update_location_Click(object sender, EventArgs e) { con.Open(); string name = NameLabel.Text; SqlCommand dataAdapter = new SqlCommand("UPDATE dbLocation SET loc_name = @loc_name WHERE loc_name = '" + name + "'", con); dataAdapter.Parameters.AddWithValue("@loc_name", textbox_location.Text); dataAdapter.ExecuteNonQuery(); SqlCommand dataAdapter2 = new SqlCommand("UPDATE DB_Main SET Location = @location WHERE Location = '" + name + "'", con); dataAdapter2.Parameters.AddWithValue("@location", textbox_location.Text); dataAdapter2.ExecuteNonQuery(); con.Close(); MessageBox.Show("Location updated!"); this.Close(); }
问题原因分析
- SQL拼接导致匹配失效:WHERE子句直接拼接
name变量,若名称包含单引号、前后空格或大小写差异,会导致SQL语句匹配不到目标行,甚至触发语法错误,最终UPDATE操作无实际效果。 - 无事务保障:两个更新操作未绑定事务,若其中一个执行失败,会出现数据不一致的情况。
- 输入未做校验:未检查新旧位置名称是否为空,可能触发无效操作。
修复后的代码
private void Update_location_Click(object sender, EventArgs e) { // 校验输入有效性 if (string.IsNullOrWhiteSpace(NameLabel.Text) || string.IsNullOrWhiteSpace(textbox_location.Text)) { MessageBox.Show("位置名称不能为空!"); return; } using (var transaction = con.BeginTransaction()) { try { con.Open(); string oldName = NameLabel.Text.Trim(); string newName = textbox_location.Text.Trim(); // 更新dbLocation表,全程使用参数化查询 var updateLocCmd = new SqlCommand("UPDATE dbLocation SET loc_name = @newName WHERE loc_name = @oldName", con, transaction); updateLocCmd.Parameters.AddWithValue("@newName", newName); updateLocCmd.Parameters.AddWithValue("@oldName", oldName); int locRowsAffected = updateLocCmd.ExecuteNonQuery(); // 校验是否找到要修改的旧位置 if (locRowsAffected == 0) { transaction.Rollback(); MessageBox.Show("未找到匹配的旧位置,请检查名称是否正确!"); con.Close(); return; } // 更新DB_Main表 var updateMainCmd = new SqlCommand("UPDATE DB_Main SET Location = @newName WHERE Location = @oldName", con, transaction); updateMainCmd.Parameters.AddWithValue("@newName", newName); updateMainCmd.Parameters.AddWithValue("@oldName", oldName); int mainRowsAffected = updateMainCmd.ExecuteNonQuery(); transaction.Commit(); MessageBox.Show($"更新完成!dbLocation修改{locRowsAffected}行,DB_Main修改{mainRowsAffected}行"); this.Close(); } catch (Exception ex) { transaction.Rollback(); MessageBox.Show($"更新失败:{ex.Message}"); } finally { if (con.State == System.Data.ConnectionState.Open) con.Close(); } } }
关键优化点
- 参数化查询:彻底替代字符串拼接,避免SQL注入风险,同时保证特殊字符、空格、大小写的正确匹配。
- 事务处理:用事务包裹两个更新操作,确保操作原子性,要么全部成功,要么全部回滚。
- 输入校验与行影响数校验:提前过滤无效输入,通过返回值判断操作是否生效,及时给用户反馈。
- 去除空格:对新旧名称做
Trim()处理,避免因前后空格导致的匹配失败。
内容的提问来源于stack exchange,提问作者Lawr Costin
相关产品推荐
相关产品推荐

