WinForm 数据库【新增+编辑】完整功能(参数化查询+配置文件+防报错全套)

一、功能整体介绍

本窗体实现同一个窗口复用 新增数据 / 编辑数据双功能:

  • 通过重载构造函数传递标记 isEdit、主键ID 区分新增/编辑模式

  • 下拉框动态绑定性别数据(全部/男/女),设置显示值与实际值

  • 编辑模式:根据ID参数化查询数据库,回显数据到界面控件

  • 新增/编辑提交:参数化执行 Insert / Update 语句,杜绝SQL注入

  • 前端数据合法性校验(非空、年龄范围、禁止选择默认全部项)

  • 分级异常捕获(数据库异常、程序通用异常)

  • 使用 using 自动释放数据库连接、命令资源

  • 连接字符串写入 App.config 配置文件,便于统一维护

二、前置准备(必须配置)

1. 引入命名空间

cs 复制代码
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Windows.Forms;

2. App.config 配置数据库连接字符串

cs 复制代码
<configuration>
  <connectionStrings>
    <add name="connectionString" 
         connectionString="server=192.168.215.96,1344;database=StudentDataBase;uid=sa;pwd=123456" 
         providerName="System.Data.SqlClient"/>
  </connectionStrings>
</configuration>

3. 性别下拉框实体类(辅助类)

用于绑定下拉框 文本+值 对应关系

cs 复制代码
public class Sex
{
    // 下拉显示文本
    public string Name { get; set; }
    // 下拉对应真实值
    public int Value { get; set; }
}

三、核心窗体完整代码(去重+规范优化)

cs 复制代码
namespace _01创建数据库
{
    public partial class Form2 : Form
    {
        // 标记:是否为编辑模式
        private bool isEdit;
        // 编辑数据的主键ID
        private int editId;

        // 默认构造:新增模式
        public Form2()
        {
            InitializeComponent();
            isEdit = false;
            editId = 0;
        }

        // 重载构造:支持外部传入编辑标记和ID
        public Form2(bool isedit = false, int editId = 0) : this()
        {
            this.isEdit = isedit;
            this.editId = editId;
        }

        // 读取配置文件数据库连接字符串
        public string connectionString = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;

        private void Form2_Load(object sender, EventArgs e)
        {
            // 1.初始化性别下拉框
            cobxSex.DataSource = new List<Sex>()
            {
                new Sex(){Name="全部",Value=-1},
                new Sex(){Name="男",Value=0},
                new Sex(){Name="女",Value=1},
            };
            cobxSex.DisplayMember = "Name";   // 界面显示字段
            cobxSex.ValueMember = "Value";     // 后台取值字段

            // 2.判断模式:编辑 / 新增
            if (isEdit)
            {
                // 编辑模式:根据ID查询数据回显
                this.Text = "编辑";
                btnAdd.Text = "编辑";

                using (SqlConnection coon = new SqlConnection(connectionString))
                {
                    if (coon.State != ConnectionState.Open)
                        coon.Open();

                    // 参数化查询(防SQL注入)
                    string sql = "select * from First where Id = @Id";
                    SqlCommand cmd = new SqlCommand(sql, coon);
                    cmd.Parameters.Add(new SqlParameter("@Id", SqlDbType.Int) { Value = editId });

                    SqlDataReader reader = cmd.ExecuteReader();
                    if (reader.Read())
                    {
                        // 回显姓名
                        txtName.Text = reader["Name"].ToString();
                        // 回显年龄
                        numAge.Value = (int)reader["Age"];

                        // 性别空值判断
                        if (reader.IsDBNull(reader.GetOrdinal("Sex")))
                            cobxSex.SelectedValue = -1;
                        else
                            cobxSex.SelectedValue = (bool)reader["Sex"] ? 1 : 0;

                        // 生日空值判断
                        if (!reader.IsDBNull(reader.GetOrdinal("Birthday")))
                            dateBirthday.Value = Convert.ToDateTime(reader["Birthday"]);
                        else
                            dateBirthday.Value = DateTime.Now;
                    }
                    reader.Close();
                }
            }
            else
            {
                // 新增模式
                this.Text = "添加";
                btnAdd.Text = "添加";
            }
        }

        // 提交按钮:新增 / 编辑 统一提交
        private void btnAdd_Click(object sender, EventArgs e)
        {
            #region 前端数据校验(防呆)
            string name = txtName.Text.Trim();
            if (string.IsNullOrEmpty(name))
            {
                MessageBox.Show("姓名不能为空");
                txtName.Focus();
                return;
            }

            int age = (int)numAge.Value;
            if (age < 0 || age > 120)
            {
                MessageBox.Show("年龄不合法");
                numAge.Focus();
                return;
            }

            int sexNum = (int)cobxSex.SelectedValue;
            if (sexNum == -1)
            {
                MessageBox.Show("请选择男或女,不能选择全部");
                cobxSex.Focus();
                return;
            }

            // 转换性别布尔值
            bool sex = sexNum == 1;
            DateTime birthday = dateBirthday.Value;
            #endregion

            string sql = string.Empty;
            List<SqlParameter> paramList = new List<SqlParameter>();

            #region 拼接SQL与参数
            if (isEdit)
            {
                // 编辑语句:Update
                sql = @"Update First set Name = @Name ,Age= @Age ,Sex=@Sex , Birthday = @Birthday  where Id =@Id";
                paramList.Add(new SqlParameter("@Id", editId));
            }
            else
            {
                // 新增语句:Insert
                sql = @"insert into First(Name,Age,Sex,Birthday) values(@Name ,@Age ,@Sex ,@Birthday)";
            }

            // 公共参数
            paramList.Add(new SqlParameter("@Name", name));
            paramList.Add(new SqlParameter("@Age", age));
            paramList.Add(new SqlParameter("@Sex", sex));
            paramList.Add(new SqlParameter("@Birthday", birthday));
            #endregion

            #region 数据库执行 + 异常捕获
            try
            {
                using (SqlConnection conn = new SqlConnection(connectionString))
                {
                    using (SqlCommand cmd = new SqlCommand(sql, conn))
                    {
                        cmd.Parameters.AddRange(paramList.ToArray());
                        conn.Open();
                        // 增删改执行方法,返回受影响行数
                        int rows = cmd.ExecuteNonQuery();

                        if (rows > 0)
                        {
                            MessageBox.Show(isEdit ? "编辑成功" : "新增成功");
                            this.DialogResult = DialogResult.OK;
                            this.Close();
                        }
                        else
                        {
                            MessageBox.Show("操作失败,未修改任何数据");
                        }
                    }
                }
            }
            catch (SqlException ex)
            {
                MessageBox.Show($"数据库异常:{ex.Message}", "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"程序异常:{ex.Message}", "操作失败", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            #endregion
        }
    }
}

四、核心考点详解(期末必考)

1. 窗口复用原理

  • 通过重载构造函数,外部可传参标记新增/编辑状态

  • isEdit=false:新增模式,清空界面、执行Insert

  • isEdit=true:编辑模式,根据editId回显数据、执行Update

2. 配置文件优势

  • 连接字符串统一放在App.config,无需改代码、直接改配置即可切换数据库

  • 避免硬编码,项目规范、便于维护

3. 参数化查询核心作用

  • 彻底防止SQL注入攻击

  • 自动处理特殊字符、数据类型转换,避免语法报错

4. using资源释放

SqlConnection、SqlCommand 实现了IDisposable接口,using执行完毕自动关闭连接、释放资源,杜绝数据库连接泄露。

5. 空值处理

使用 reader.IsDBNull() 判断数据库可空字段,避免读取空数据时报错,是数据库项目必备容错写法。

6. ExecuteNonQuery 方法

专门用于增、删、改 操作,返回值为受影响的数据行数,大于0代表操作成功。

五、调用方式(父窗体打开弹窗)

cs 复制代码
// 打开新增窗口
Form2 addForm = new Form2();
addForm.ShowDialog();

// 打开编辑窗口(假设编辑ID=1)
Form2 editForm = new Form2(true,1);
editForm.ShowDialog();

六、代码优化亮点(考试加分点)

  • 去除重复代码,统一新增/编辑提交逻辑

  • 分级异常捕获,区分数据库错误和程序错误

  • 完善前端校验,拦截非法数据

  • 下拉框绑定实体类,规范性强

  • 所有数据库操作使用using,符合.NET最优规范

七、绑定数据源过程

  • 创建链接,并且打开 SqlConnection conn = new SqlConnection(connectionString);

  • 创建一个传递参数的对象 如果传递多个参数 定义成参数数组 SqlParameter\[\] sqlParas = new SqlParameter\[\]

  • 把参数赋值 sqlParas0.Value 或 List<SqlParameter> list = new List<SqlParameter>();

  • 组织Sql语句

  • 创建一个命令 SqlCommand cmd = new SqlCommand (sql, conn);

  • 开始执行sql遇见执行之前把参数数组清空 cmd.Parameters.Clear (); cmd.Parameters.AddRange (sqlParas);//添加Sql语句参数 SqlDataReader reader = cmd.ExecuteReader ();

  • 取出数据 展示到界面上 DataTable dt=new DataTable(); dt.Load(reader);

    dataGridView1.DataSource = dt;

  • 关闭连接

相关推荐
迷枫7121 小时前
达梦数据库 Hint 使用与 Hint 注入实战
数据库
Gauss松鼠会3 小时前
【GaussDB】GaussDB锁阻塞源头查询
java·开发语言·前端·数据库·算法·gaussdb·经验总结
2601_965798473 小时前
How to Build a Custom Artisan Store on WordPress: Crafti Theme Review
linux·服务器·数据库
霸道流氓气质3 小时前
Spring 事务传播机制与 REQUIRES_NEW
java·数据库·spring
YOU OU4 小时前
Redis分布式锁
数据库·redis·分布式
小草儿7994 小时前
GBase 8s CLOB → VARCHAR(32739) 数据迁移方案文档
数据库
秋田君4 小时前
QT_QColorDialog颜色对话框
java·数据库·qt
涛声依旧393164 小时前
运维项目:InnoAI SQL 助手
运维·数据库·sql
万悉科技4 小时前
时尚品牌GEO技术选型指南:LLM原生优化与AI记忆构建全解析
数据库·人工智能·搜索引擎