C# WinForm提交费用数据时fees表重复插入两条相同记录问题
问题背景
- 开发技术栈:C# WinForm
- 数据库信息:库名
School,其中fees表包含stu_id、fees两个字段 - 故障表现:前端提交费用信息后,数据库会新增2条完全相同的记录,不符合预期的单条插入逻辑,其他窗体编写的同类插入逻辑未出现该异常。

问题复现代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; namespace SchoolManagementSystem { public partial class Fees : Form { public Fees() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { SqlConnection con = new SqlConnection(@"Data Source=DRAGON\SQLEXPRESS;Initial Catalog=School;Integrated Security=True;"); con.Open(); try { string str = " INSERT INTO fees VALUES('" + textBox1.Text + "','" + textBox2.Text + "')"; SqlCommand cmd = new SqlCommand(str, con); cmd.ExecuteNonQuery(); SqlDataReader dr = cmd.ExecuteReader(); if (dr.Read()) { MessageBox.Show("Your Fees Submitted.."); this.Hide(); Home obj2 = new Home(); obj2.ShowDialog(); } this.Close(); } catch (SqlException excep) { MessageBox.Show(excep.Message); } con.Close(); } private void textBox1_MouseLeave(object sender, EventArgs e) { textBox2.Text = ""; SqlConnection con = new SqlConnection(@"Data Source=DRAGON\SQLEXPRESS;Initial Catalog=School;Integrated Security=True;"); con.Open(); if (textBox1.Text != "") { try { string getCust = "select name,standard,medium from student where std_id=" + Convert.ToInt32(textBox1.Text) + " ;"; SqlCommand cmd = new SqlCommand(getCust, con); SqlDataReader dr; dr = cmd.ExecuteReader(); if (dr.Read()) { label9.Text = dr.GetValue(0).ToString(); label6.Text = dr.GetValue(1).ToString(); label7.Text = dr.GetValue(2).ToString(); } else { MessageBox.Show("Sorry '" + textBox1.Text + "' This Registration Id is Invalid, Please Insert Correct Id"); textBox1.Text = ""; textBox2.Text = ""; } } catch (SqlException excep) { MessageBox.Show(excep.Message); } con.Close(); } } private void textBox2_TextChanged(object sender, EventArgs e) { } private void Fees_Load(object sender, EventArgs e) { } } }
故障根因
重复插入的核心原因是同一条INSERT语句被执行了两次:
- 第一次执行:调用
cmd.ExecuteNonQuery()时,已经向fees表插入了1条记录 - 第二次执行:后续又对同一个绑定了INSERT语句的
cmd对象调用cmd.ExecuteReader(),该方法会再次执行绑定的SQL语句,导致第二次插入重复记录。
额外存在的逻辑错误:INSERT属于增删改操作,执行后不会返回结果集,后续的dr.Read()判断本身没有实际意义,永远不会进入写好的成功提示分支。
同时代码还存在SQL注入风险、数据库资源未可靠释放的隐患。
修复方案
- 删除多余的
cmd.ExecuteReader()相关逻辑,INSERT操作仅需调用ExecuteNonQuery()即可,通过该方法的返回值(受影响行数)判断是否插入成功 - 建议改用参数化查询避免SQL注入,使用
using块自动释放数据库连接、命令等非托管资源,避免资源泄漏。
修复后的提交按钮点击事件参考代码:
private void button1_Click(object sender, EventArgs e) { // using块会在代码执行结束后自动释放连接资源,不需要手动调用Close using (SqlConnection con = new SqlConnection(@"Data Source=DRAGON\SQLEXPRESS;Initial Catalog=School;Integrated Security=True;")) { try { con.Open(); // 用参数化写法替代SQL拼接,避免注入风险,明确指定插入字段避免表结构变动后出错 string str = "INSERT INTO fees(stu_id, fees) VALUES(@stuId, @fees)"; using (SqlCommand cmd = new SqlCommand(str, con)) { // 给参数赋值,可根据字段实际类型指定SqlDbType提升查询效率 cmd.Parameters.AddWithValue("@stuId", textBox1.Text.Trim()); cmd.Parameters.AddWithValue("@fees", textBox2.Text.Trim()); // ExecuteNonQuery返回受影响的行数,等于1代表插入成功 int affectRows = cmd.ExecuteNonQuery(); if (affectRows > 0) { MessageBox.Show("费用提交成功"); this.Hide(); Home obj2 = new Home(); obj2.ShowDialog(); } } this.Close(); } catch (SqlException excep) { MessageBox.Show(excep.Message); } } }
内容的提问来源于stack exchange,提问作者Shehrooz
相关产品推荐
相关产品推荐

