如何使用C#将DataGridView的修改同步更新到MySQL数据库
问题排查与修复方案
核心错误点
- 你当前的
MySql_Update方法逻辑完全颠倒:执行更新时先调用myadapter.Fill(dtTable)会直接从数据库拉取最新数据覆盖你之前修改好的dtTable,导致最后提交更新的是完全没改动的原始数据,自然不会有写入效果 - 你在校验修改
DataGridView数据后没有调用结束编辑的方法,部分修改可能还停留在UI缓存没有同步到绑定的dtTable中 MySqlCommandBuilder要求查询的表必须有主键,否则无法自动生成有效的UPDATE/DELETE语句- 数据库连接、Command对象没有释放,容易出现资源泄漏
修复步骤
第一步:调整全局变量的初始化逻辑
首先确保myadapter、dtTable是全局变量,且在窗体加载时只初始化一次,绑定DataGridView的逻辑放在窗体加载事件里,不要每次更新都重新绑定:
// 全局变量定义 MySqlDataAdapter myadapter; DataTable dtTable; MySqlCommandBuilder cmb; // 窗体加载事件里执行一次初始化绑定 private void Form1_Load(object sender, EventArgs e) { MySqlConnection connection = new MySqlConnection(configuracion.conexion); string query = "SELECT * FROM TEST.PRUEBA;"; try { connection.Open(); myadapter = new MySqlDataAdapter(query, connection); cmb = new MySqlCommandBuilder(myadapter); dtTable = new DataTable(); myadapter.Fill(dtTable); myadapter.FillSchema(dtTable, SchemaType.Source); dataGridView2.DataSource = dtTable; } catch(MySqlException ex) { createLog(ex.ToString()); MessageBox.Show("初始化数据加载失败:" + ex.Message); } finally { connection?.Close(); connection?.Dispose(); } }
第二步:修改校验方法,确保修改同步到DataTable
在校验结束后调用EndEdit确认所有修改提交到绑定的DataTable:
private void btndepurar_Click(object sender, EventArgs e) { Cursor.Current = Cursors.WaitCursor; try { // 先结束当前可能的编辑状态 dataGridView2.EndEdit(); if(dtTable != null) dtTable.AcceptChanges(); for (int i = 0; i < dataGridView2.Rows.Count-1; i++) { dataGridView2.Rows[i].Cells["COURT_CASE"].Value = Valida_Cc(dataGridView2.Rows[i].Cells["COURT_CASE"].Value.ToString()); dataGridView2.Rows[i].Cells["BALANCE"].Value = validar_balance(dataGridView2.Rows[i].Cells["BALANCE"].Value.ToString()); dataGridView2.Rows[i].Cells["COURT_CITY"].Value = FixCourtCities(dataGridView2.Rows[i].Cells["COURT_CITY"].Value.ToString()); dataGridView2.Rows[i].Cells["COMMENTS"].Value = Validar_Com(dataGridView2.Rows[i].Cells["COMMENTS"].Value.ToString()); dataGridView2.Rows[i].Cells["COURT_NUMBER"].Value = Validar_Cn(dataGridView2.Rows[i].Cells["COURT_NUMBER"].Value.ToString(), (Int32)dataGridView2.Rows[i].Cells["LINK_REFERENCE"].Value, dataGridView2.Rows[i].Cells["COURT_CASE"].Value.ToString()); dataGridView2.Rows[i].Cells["PROCESS_TYPE"].Value = Validar_Pt(dataGridView2.Rows[i].Cells["PROCESS_TYPE"].Value.ToString()); } // 校验完再次确认修改同步到DataTable dataGridView2.EndEdit(); } catch (Exception ex) { MessageBox.Show("校验失败:" + ex.Message); createLog(ex.ToString()); } finally { Cursor.Current = Cursors.Default; } }
第三步:重写更新方法,移除重复Fill逻辑
更新时直接提交修改后的DataTable即可,不要重新拉取数据覆盖:
private void MySql_Update() { if(dtTable == null || dtTable.GetChanges() == null) { createLog("无需要更新的数据"); return; } MySqlConnection connection = new MySqlConnection(configuracion.conexion); try { connection.Open(); myadapter.UpdateCommand = cmb.GetUpdateCommand(); // 直接提交修改后的DataTable,不要执行Fill操作 int affectRows = myadapter.Update(dtTable); dtTable.AcceptChanges(); createLog($"更新成功,影响行数:{affectRows}"); } catch (MySqlException ex) { createLog(ex.ToString()); MessageBox.Show("更新失败:" + ex.Message); } finally { connection?.Close(); connection?.Dispose(); } } private void btnActualizarBD_Click(object sender, EventArgs e) { MySql_Update(); }
额外注意事项
- 确认你的
TEST.PRUEBA表已经设置主键,否则MySqlCommandBuilder无法生成更新语句,需要手动写更新SQL - 如果更新后还是失败,可以在
MySql_Update方法里打印cmb.GetUpdateCommand().CommandText,确认生成的更新语句是否正确 - 所有的
Value.ToString()调用前建议先判断是否为DBNull,避免空引用报错
内容的提问来源于stack exchange,提问作者Juan Sastre
相关产品推荐
相关产品推荐

