手把手教你用C# WinForms + ADO.NET实现学员信息管理(增删改)
一、项目概述本程序实现了一个基于SQL Server数据库的学员信息管理工具主要功能包括添加学员录入编号、姓名、性别、年龄修改学员根据学员编号修改其性别和年龄删除学员支持按姓名删除、按编号删除界面使用WinForms设计分为三个区域如下图:二、整体思路拿到需求后我的设计步骤如下数据库设计创建stuInfo表包含stuNo(学员编号,主键)、stuName、stuSex、stuAge四个字段。界面布局用Panel分区使用TextBox输入文本ComboBox选择年龄15-30岁RadioButton选择性别。数据操作采用ADO.NET的SqlConnection、SqlCommand编写SQL语句实现增删改。异常处理与验证对用户输入做非空校验操作前先查询数据是否存在避免直接操作失败。三、准备工作IDEVisual Studio 2019/2022.NET版本.NET Framework 4.5数据库SQL Server 2012本例使用本地实例server.数据库表脚本CREATE DATABASE student; GO USE student; GO CREATE TABLE stuInfo ( stuNo NVARCHAR(20) PRIMARY KEY, stuName NVARCHAR(50) NOT NULL, stuSex NCHAR(1) CHECK(stuSex IN (男,女)), stuAge INT CHECK(stuAge BETWEEN 15 AND 30) ); GO四、核心代码解析1. 窗体加载 – 初始化年龄下拉框在Form1_Load事件中为两个年龄ComboBox动态添加15~30的数字。private void Form1_Load(object sender, EventArgs e) { // 添加学员区的年龄下拉框 for (int i 15; i 30; i) { comboBox_age.Items.Add(i); } comboBox_age.SelectedIndex 0; // 默认选中15 // 修改学员区的年龄下拉框 for (int i 15; i 30; i) { comboBox_exAge.Items.Add(i); } }思路固定范围选择避免了用户输入非法年龄。2. 添加学员 – 完整业务流程步骤非空校验编号、姓名、性别从控件取值年龄需转为int连接数据库执行INSERT成功后清空表单关键代码private void button_add_Click(object sender, EventArgs e) { // 1. 非空判断 if (string.IsNullOrWhiteSpace(textBox_ID.Text)) { MessageBox.Show(请输入学员编号); return; } // ... 姓名、性别校验性别必须二选一 string stuId textBox_ID.Text; string stuName textBox_name.Text; string stuSex radioB_man.Checked ? 男 : 女; int stuAge Convert.ToInt32(comboBox_age.SelectedItem); // 2. 数据库插入 using (SqlConnection con new SqlConnection(server.;uidsa;pwd123;databasestudent)) { con.Open(); string sql $INSERT INTO stuInfo VALUES ({stuId},{stuName},{stuSex},{stuAge}); using (SqlCommand cmd new SqlCommand(sql, con)) { int result cmd.ExecuteNonQuery(); if (result 0) { MessageBox.Show(添加成功); ClearAddForm(); // 自定义清空方法 } else MessageBox.Show(添加失败); } } }⚠️注意代码中性别获取逻辑存在隐患 – 若两个RadioButton都未选中会默认“女”。实际应该先判断提示用户选择。我后来优化成了if-else结构。3. 修改学员 – 先查后改修改的核心思路根据用户输入的编号先查询数据库中是否存在该学员若存在再执行UPDATE。private void button_exchange_Click(object sender, EventArgs e) { // 非空校验 if (string.IsNullOrWhiteSpace(textBox_exID.Text)) { MessageBox.Show(请输入要修改的学员编号); return; } string exstuID textBox_exID.Text; using (SqlConnection con new SqlConnection(connectionString)) { con.Open(); // 第一步查是否存在 string checkSql $SELECT COUNT(*) FROM stuInfo WHERE stuNo{exstuID}; using (SqlCommand checkCmd new SqlCommand(checkSql, con)) { int count (int)checkCmd.ExecuteScalar(); if (count 0) { MessageBox.Show(查询不到此学员编号); return; } } // 第二步获取新值性别、年龄 string newSex radioB_exMan.Checked ? 男 : 女; int newAge Convert.ToInt32(comboBox_exAge.SelectedItem); // 第三步更新 string updateSql $UPDATE stuInfo SET stuSex{newSex}, stuAge{newAge} WHERE stuNo{exstuID}; using (SqlCommand cmd new SqlCommand(updateSql, con)) { int result cmd.ExecuteNonQuery(); if (result 0) { MessageBox.Show(修改成功); ClearModifyForm(); } else MessageBox.Show(修改失败); } } }4. 删除学员 – 按姓名 / 按编号两个删除逻辑高度相似校验非空 → 验证存在 → 执行DELETE。以按姓名删除为例private void button_delName_Click_1(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(textBox_delName.Text)) { MessageBox.Show(请输入要删除的姓名); return; } using (SqlConnection con new SqlConnection(connectionString)) { con.Open(); // 验证姓名是否存在 string checkSql $SELECT COUNT(*) FROM stuInfo WHERE stuName{textBox_delName.Text}; using (SqlCommand cmd new SqlCommand(checkSql, con)) { int count (int)cmd.ExecuteScalar(); if (count 0) { MessageBox.Show(你输入的姓名不存在); return; } } // 执行删除注意会删除所有同名的记录 string delSql $DELETE FROM stuInfo WHERE stuName{textBox_delName.Text}; using (SqlCommand cmd new SqlCommand(delSql, con)) { int count cmd.ExecuteNonQuery(); if (count 0) MessageBox.Show(删除成功); } } }按编号删除代码类似这里不再重复。五、开发中遇到的问题 反思 问题1SQL注入风险整个项目中使用的是字符串拼接SQL例如$SELECT COUNT(*) FROM stuInfo WHERE stuNo{exstuID}如果用户在文本框输入 OR 11后果不堪设想。这是严重的安全隐患。✅解决方案使用参数化查询。例如string sql INSERT INTO stuInfo VALUES (no,name,sex,age); SqlCommand cmd new SqlCommand(sql, con); cmd.Parameters.AddWithValue(no, stuId); // ... 其他参数 问题2数据库连接字符串硬编码代码中直接写死了server.;uidsa;pwd123;databasestudent一旦数据库密码或服务器变更必须重新编译程序。✅改进将连接字符串写入App.config配置文件通过ConfigurationManager读取。 问题3控件事件绑定错误设计文件中button3被命名为“修改”按钮却绑定了button_exchange_Click事件这个事件是修改学员区的。这是个明显的复制粘贴错误。✅修正删除button3或为其编写正确的删除逻辑。 问题4删除后未清空输入框添加/修改成功后清空了表单但删除成功后没有清空对应的文本框用户体验欠佳。✅改进在删除成功后调用textBox_delName.Clear()等。 问题5年龄获取时的类型转换代码中使用Convert.ToInt32(comboBox_age.SelectedItem)但如果用户未选择SelectedItem为null会抛出异常。虽然我初始化时设置了SelectedIndex0但严谨起见应该判断。✅优化if (comboBox_age.SelectedItem null || !int.TryParse(comboBox_age.SelectedItem.ToString(), out int age)) { MessageBox.Show(请选择有效年龄); return; } 问题6数据库连接未显式关闭代码中多处写了con.Close()但实际上using块结束时会自动释放并关闭连接无需手动调用。手动调用也可能引发二次释放问题。✅建议去掉所有显式的Close()依赖using即可。六、总结通过这个小项目我们实践了WinForms的常用控件用法、ADO.NET的核心对象Connection、Command、ExecuteNonQuery/ExecuteScalar以及数据库的增删改基本操作。同时也暴露了代码中常见的几个坑忘记校验性别是否选中忽略SQL注入风险事件绑定错乱资源管理可以更优雅收获以后写数据库交互代码我会默认使用参数化查询配置文件存储连接字符串完善的输入验证。希望这篇博客也能让正在学习C#数据库编程的你少走一些弯路。如果你有任何疑问或发现了其他bug欢迎在评论区交流讨论