使用C# CurrencyManager AddNew()方法无法更新数据库记录求助
你遇到的问题是,通过CurrencyManager.AddNew()和EndCurrentEdit()虽然在内存的DataTable里创建了新记录,但这些变化并没有同步到实际的数据库中。下面是你的完整代码:
namespace currencyManager { public partial class Form1 : Form { public Form1() { InitializeComponent(); } SqlConnection con; SqlCommand cmd; SqlDataAdapter da; DataTable dt; CurrencyManager cm; private void Form1_Load(object sender, EventArgs e) { con = new SqlConnection("data source=COUNTER16-PC,initial catalog=myDatabase;integrated security=true"); con.Open(); cmd = new SqlCommand("Select * from Students", con); da = new SqlDataAdapter(); da.SelectCommand = cmd; dt = new DataTable(); da.Fill(dt); cm = (CurrencyManager)BindingContext[dt]; txtID.DataBindings.Add("text",dt,"ID"); txtFname.DataBindings.Add("text", dt, "FirstName"); txtLname.DataBindings.Add("text", dt, "LASTNAME"); txtState.DataBindings.Add("text", dt, "STATE"); txtPhone.DataBindings.Add("text", dt, "PHONE"); txtEmail.DataBindings.Add("text", dt, "EMAIL"); txtGrade.DataBindings.Add("text", dt, "GRADEYEAR"); txtGrade.DataBindings.Add("text", dt, "GPA"); txtProgram.DataBindings.Add("text", dt, "PROGRAM"); txtNews.DataBindings.Add("text", dt, "NEWLETTER"); } private void btn_first_Click(object sender, EventArgs e) { cm.Position = 0; } private void btn_prev_Click(object sender, EventArgs e) { cm.Position--; } private void btn_next_Click(object sender, EventArgs e) { cm.Position++; } private void btn_last_Click(object sender, EventArgs e) { cm.Position = cm.Count - 1; } private void btn_add_Click(object sender, EventArgs e) { cm.AddNew(); } private void btn_save_Click(object sender, EventArgs e) { cm.EndCurrentEdit(); } private void btn_update_Click(object sender, EventArgs e) { } private void btn_delete_Click(object sender, EventArgs e) { cm.RemoveAt(cm.Position); } } }
CurrencyManager的操作只针对内存中的DataTable,而你使用的SqlDataAdapter默认只配置了SelectCommand用来查询数据,没有对应的InsertCommand、UpdateCommand和DeleteCommand来将DataTable的变更同步回数据库。你调用cm.EndCurrentEdit()只是确认了内存中数据的修改,但没有触发任何数据库写入操作。
我们需要添加SqlCommandBuilder来自动生成所需的更新命令,然后在保存时调用SqlDataAdapter.Update()方法将变更提交到数据库。同时,建议优化数据库连接的管理(避免长期保持连接打开):
步骤1:添加SqlCommandBuilder自动生成更新命令
在Form1_Load方法中,创建SqlDataAdapter后,添加SqlCommandBuilder——它会根据你的SelectCommand自动生成对应的增删改命令:
da = new SqlDataAdapter(cmd); // 简化代码,直接把查询命令传入构造函数 SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da);
注意:
SqlCommandBuilder要求查询的表必须有主键(比如你的ID字段),否则无法自动生成正确的更新命令,请确保Students表已设置主键。
步骤2:修改保存按钮的事件逻辑
更新btn_save_Click方法,在结束内存数据编辑后,调用da.Update(dt)把DataTable的变更同步到数据库:
private void btn_save_Click(object sender, EventArgs e) { cm.EndCurrentEdit(); try { // 将DataTable的所有变更提交到数据库 int rowsAffected = da.Update(dt); MessageBox.Show($"成功更新 {rowsAffected} 条记录"); } catch (Exception ex) { MessageBox.Show($"保存失败:{ex.Message}"); } }
步骤3:优化数据库连接管理(可选但推荐)
避免长期保持数据库连接打开,用using语句管理连接,确保连接会被正确释放:
private void Form1_Load(object sender, EventArgs e) { string connectionString = "data source=COUNTER16-PC,initial catalog=myDatabase;integrated security=true"; // using语句会自动释放连接资源 using (SqlConnection con = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand("Select * from Students", con); da = new SqlDataAdapter(cmd); SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da); dt = new DataTable(); da.Fill(dt); // Fill方法会自动打开/关闭连接(如果连接原本是关闭状态) } cm = (CurrencyManager)BindingContext[dt]; // 控件绑定代码保持不变... }
完整修改后的关键代码片段
SqlDataAdapter da; DataTable dt; CurrencyManager cm; private void Form1_Load(object sender, EventArgs e) { string connectionString = "data source=COUNTER16-PC,initial catalog=myDatabase;integrated security=true"; using (SqlConnection con = new SqlConnection(connectionString)) { SqlCommand cmd = new SqlCommand("Select * from Students", con); da = new SqlDataAdapter(cmd); // 自动生成增删改命令 SqlCommandBuilder cmdBuilder = new SqlCommandBuilder(da); dt = new DataTable(); da.Fill(dt); } cm = (CurrencyManager)BindingContext[dt]; // 控件绑定代码... } private void btn_save_Click(object sender, EventArgs e) { cm.EndCurrentEdit(); try { int updatedRows = da.Update(dt); MessageBox.Show($"已成功保存 {updatedRows} 条记录到数据库"); } catch (Exception ex) { MessageBox.Show($"保存出错:{ex.Message}"); } }
这样修改后,当你点击添加按钮创建新记录、输入内容后点击保存,数据就会正确同步到数据库中了。
内容的提问来源于stack exchange,提问作者Mehdi Sedaqat

