简介:基于C# WinForm与MySQL的人事工资管理系统源码包,主要面向需要完成人事管理课程设计或希望学习桌面端管理信息系统开发的读者。资源共47个文件,包含28个C#窗体与逻辑代码、10个resx界面布局资源、SQL数据库脚本、项目解决方案及说明文档,压缩包仅857KB,轻量易用。系统已实现登录与权限校验、管理员/员工信息管理、部门管理、工资数据管理等模块,并通过mysql.data.dll完成数据库访问,配套hr.sql可直接导入MySQL、运行说明帮助快速启动。已有382人学习下载,这份代码在项目分层、界面事件绑定、SQL操作封装等方面能提供清晰参考,适合二次开发或巩固C#+MySQL实战能力。
1. 一套能直接跑的 C# Winform + MySQL 人事工资管理系统:先搞清楚它到底解决什么问题
你翻到这份资源,大概率是想找一个能写进简历、能应付课程设计、又能让自己真正看懂的 Winform 项目。市面上的教务系统、图书管理系统看得眼花,但真正把「管理员 → 部门 → 员工 → 工资 → 数据展示」这一整条业务链走完的并不多。这套人事工资管理系统就是干这个的:登录、改密码、管管理员、管部门、管员工、算工资、看数据,全在一个 Winform 工程里闭环。它自带 hr.sql 数据库脚本和 mysql.data.dll,意味着你不用自己拼连接层,导入数据库、改个连接串就能跑起来。适合刚学完 C# 基础、想拿真实项目练手的人,也适合急着交课程设计但又不想从零起工程的人。至于熟手,本文后面会讲清楚这套代码的边界和坑,拿来二次开发完全够用。
2. 系统结构与技术选型:从登录到工资结算的模块拆解,以及为什么是 Winform + MySQL
2.1 模块地图:每个文件对应哪块业务
这套系统的工程文件不是随便堆的,文件命名基本能看出分层思路。先看核心业务文件:
| 文件名 | 对应功能 | 说明 |
|---|---|---|
| login.cs / login.Designer.cs | 登录窗口 | 校验账号密码,登录成功后打开主界面 |
| 管理员主界面.cs | 主窗体 | 菜单入口,承载各功能模块跳转 |
| 管理管理员.cs | 管理员账号管理 | 增删改管理员,设置权限 |
| 部门管理.cs | 部门信息维护 | 部门编号、名称,员工挂靠的基础 |
| 管理员工.cs | 员工档案管理 | 员工基本信息录入、修改、删除 |
| 工资管理.cs | 工资结算 | 按员工/月份录入工资,计算实发 |
| 数据显示.cs | 数据展示 | 列表/汇总展示,配合 DataGridView |
| 修改密码.cs | 密码修改 | 传入当前用户,校验旧密码后更新 |
| Staff.cs / User.cs / Wage.cs / department.cs | 实体类 | 对应员工、用户、工资、部门的字段封装 |
| MyDB.cs / mysql.cs | 数据库操作层 | 连接 MySQL、执行 SQL、返回结果集 |
| ComboxItem.cs | 辅助类 | 下拉框绑定用的键值对封装 |
这里有个值得注意的点:所有的业务窗体旁边都有对应的.Designer.cs文件,那是 VS 自动生成的界面布局代码,你拖动控件时它自己改,一般不用手碰。Program.cs是整个程序的入口,默认启动 login 窗体。README.md是运行说明,里面应该写了环境要求和导入步骤,下载后务必先读它。
从职责看,这套代码没有用三层架构,属于典型的「窗体一个文件夹、数据层一个类」的紧凑结构。好处是小项目容易看懂,坏处是如果业务继续膨胀,MyDB.cs 会变成大杂烩。不过对学习来说,这种结构反而比过度封装更容易上手。
2.2 为什么是 Winform + MySQL 而不是 WPF + SQLite
你可能会有疑问:现在 new 项目不是都推荐 WPF 或者 .NET MAUI 吗?为什么还要看 Winform?这里有几个实际原因。
第一,Winform 的控件模型简单直白。你的按钮事件、数据绑定、DataGridView 操作,全都是拖拽 + 双击写事件的路子,对于刚接触桌面开发的入门者,Winform 是把「界面」和「代码」对应起来的最短路径。WPF 的 MVVM、绑定、模板会把逻辑复杂度拉高一个级别,很多人还没写到登录界面就在数据模板上卡住了。
第二,MySQL 是真实项目里出现频率最高的免费数据库。相比 SQLite 更适合嵌入式,MySQL 是标准的 C/S 架构数据库,连接串、驱动、授权这些坑你在入职后还会遇到一遍。提前用这套系统把 MySQL 的常用玩法练熟,比用 Access 或 SQLite 写课程设计更有说服力。
第三,这套资源里已经带了mysql.data.dll,这是官方 MySQL .NET 连接器。你不需要自己去 NuGet 里折腾版本,直接用本地 DLL 引用,少踩一个「引用包装不上」的坑。这一点对网络不稳定或者不熟悉 VS 包管理的人来说非常友好。
说到选型还有一个隐性好处:Winform + MySQL 的组合在中小企业内部管理系统里仍然大量存在,尤其是制造、仓储、人事这类传统业务。你会写这套技术栈,意味着到了项目里能直接接手现成的维护任务,而不是只会写纯新的玩具。
3. 把环境搭起来:VS 版本、MySQL 版本、SQL 脚本导入与连接串配置
3.1 环境准备清单:软件版本怎么配才不打架
我第一次跑这类老工程时,光环境就折腾了大半天,血泪经验告诉你这里最容易翻车的是版本匹配。推荐组合:
- Visual Studio 2019 或 2022,装好
.NET 桌面开发工作负载,Windows 7/10/11 都能跑。 - MySQL 5.7 或 8.0,理论上两个都行,但如果你用的是 MySQL 8.0,要注意 mysql.data.dll 版本不能太老,否则会报认证协议错误。
- mysql.data.dll:资源包自带的这个 DLL 一般对应 MySQL 5.x 时代,如果是 8.0 数据库连不上,优先去 MySQL 官网下载新版 Connector/NET,把 bin 里的 DLL 替换到工程引用目录。
另外,你本机要有 MySQL 服务在跑。建议直接用你的 MySQL 安装目录下的bin/mysql.exe命令行工具,不依赖 Navicat 这类客户端也能完成导入。如果已经装了 Navicat,那直接图形化操作更省事。
3.2 导入 hr.sql:一条命令建库建表加初始数据
hr.sql 是这套系统的数据库脚本,里面应该包含建库、建表、插入管理员初始账号三个部分。导入方式按你手头工具来,命令行是最稳的。
打开 CMD 或 PowerShell,切到你 MySQL 安装的 bin 目录,然后执行:
mysql -u root -p < D:\path\to\hr.sql执行后会提示输入 root 密码,正确输入后如果看到命令行没有报错,说明导入成功。然后用下面命令检查库是否建出来:
mysql -u root -p -e "show databases like 'hr';"这里要注意-e参数是执行后面的 SQL 语句并退出,如果能看到 hr 库,就可以继续下一步。假如 hr.sql 里已经写了CREATE DATABASE hr,那你后续所有连接串里的 Database 名称就是hr,别改成别的。还有一点:如果是用 Navicat 导入,导入前先确认字符集选utf8mb4,否则中文数据容易变成乱码。
3.3 修改连接串:MyDB.cs 和 mysql.cs 里的关键配置
系统里所有数据库操作最终都会走到数据访问类,你需要在源码里找到连接串定义的位置。常见写法是在 MyDB.cs 顶部或者某个GetConn()方法里:
public static string connStr = "Server=localhost;Port=3306;Database=hr;Uid=root;Pwd=123456;CharSet=utf8;SslMode=none;";这行串里的每个参数都别改错:Server是 MySQL 所在主机,本地跑就填localhost;Port默认 3306,如果你安装时改过端口就要对应改;Database必须和 hr.sql 建的库名一致;Uid和Pwd是你 MySQL 的账号密码;CharSet=utf8保证中文不乱码;SslMode=none让你本地调试时不走 SSL 加密,避免 MySQL 8.0 默认开 SSL 导致的握手失败。
改完连接串后,可以用一个最简单的 C# 代码验证连通性。如果你不想改原工程代码,可以直接在登录窗体里加个按钮临时测试,但更推荐的做法是写个控制台小程序测试连接:
using (var conn = new MySqlConnection(MyDB.connStr)) { try { conn.Open(); MessageBox.Show("连接成功"); } catch (Exception ex) { MessageBox.Show(ex.Message); } }这里的MySqlConnection来自mysql.data.dll里的MySql.Data.MySqlClient命名空间。如果你在代码里看到 using 报错,检查一下工程里是否已经引用了这个 DLL。很多新手卡在这一步,不是代码问题,而是引用没加。
4. 核心模块实战:登录逻辑、工资管理、数据显示的代码级拆解
4.1 登录验证:参数化查询是及格线
login.cs 是整套系统的入口,它的逻辑很有代表性:输入用户名和密码,查数据库比对,成功就打开主界面,失败就提示错误。这是几乎所有管理系统都会用到的功能,代码结构也是标准的。
private void btnLogin_Click(object sender, EventArgs e) { string username = txtUser.Text.Trim(); string password = txtPwd.Text.Trim(); string sql = "SELECT COUNT(*) FROM t_admin WHERE username=@user AND password=@pwd"; MySqlParameter[] ps = { new MySqlParameter("@user", username), new MySqlParameter("@pwd", password) }; int count = Convert.ToInt32(MyDB.ExecuteScalar(sql, ps)); if (count > 0) { this.Hide(); MainForm main = new MainForm(username); main.Show(); } else { MessageBox.Show("用户名或密码错误"); } }逻辑很简单,但有几个地方值得琢磨。第一,@user和@pwd是参数化查询的占位符,对应MySqlParameter数组里的值,这种写法能有效防止 SQL 注入,比直接拼接字符串安全得多。你在二次开发时也要保持这个习惯,不要因为图方便改成"SELECT ... WHERE username='" + username + "'",否则别人能轻松绕过登录。第二,ExecuteScalar返回第一行第一列的值,这里用COUNT(*)所以返回的是一个数字,转成 int 后判断是否大于 0。如果你的数据访问类里没有现成的ExecuteScalar,看看 MyDB.cs 里是不是写了MySqlCommand.ExecuteScalar()的封装。第三,密码这里没有 hash,直接明文比对,课程设计能跑,但真实项目里一定别这么干。
4.2 工资管理:Wage.cs 里的增删改查完整套路
工资管理是这套系统的核心业务模块,它要完成新增工资记录、修改工资、按条件查询、删除记录四个动作。打开 Wage.cs 会看到类似这样的结构:
// 新增或更新工资记录 private void btnSave_Click(object sender, EventArgs e) { string staffId = cmbStaff.SelectedValue.ToString(); string year = txtYear.Text.Trim(); string month = txtMonth.Text.Trim(); string baseWage = txtBase.Text.Trim(); string bonus = txtBonus.Text.Trim(); string deduct = txtDeduct.Text.Trim(); // 实发 = 基本工资 + 奖金 - 扣款 decimal netWage = Convert.ToDecimal(baseWage) + Convert.ToDecimal(bonus) - Convert.ToDecimal(deduct); string sql = "INSERT INTO t_salary(staff_id, year, month, base_wage, bonus, deduct, net_wage) " + "VALUES(@sid, @year, @month, @base, @bonus, @deduct, @net) " + "ON DUPLICATE KEY UPDATE base_wage=@base, bonus=@bonus, deduct=@deduct, net_wage=@net"; MySqlParameter[] ps = { new MySqlParameter("@sid", staffId), new MySqlParameter("@year", year), new MySqlParameter("@month", month), new MySqlParameter("@base", baseWage), new MySqlParameter("@bonus", bonus), new MySqlParameter("@deduct", deduct), new MySqlParameter("@net", netWage) }; MyDB.ExecuteNonQuery(sql, ps); MessageBox.Show("保存成功"); }这个片段暴露了几个关键信息:工资表里保存了员工 ID、年月、基本工资、奖金、扣款和实发工资。ON DUPLICATE KEY UPDATE是 MySQL 里的「有则更新、无则插入」语法,前提是表里对(staff_id, year, month)建了唯一索引。这套代码用这个写法,省掉了先查询再判断的步骤,思路很好。你在复现时可以查看 hr.sql 里的建表语句,确认唯一索引是否存在,如果不存在,这条语句就会变成纯插入,重复保存会出多条记录。另外注意到cmbStaff.SelectedValue是从员工下拉框里取员工 ID,这个 ID 在数据表里是外键,所以在管理员工模块里删除员工前,要先删掉他的工资记录,否则外键约束会拒绝删除。
4.3 数据显示:DataGridView 绑定与刷新
数据显示.cs 负责把数据库里的数据展示到表格上,并且往往带有条件筛选。核心代码通常是这样的:
private void LoadData() { string keyword = txtKeyword.Text.Trim(); string sql = "SELECT s.staff_id, s.name, d.dept_name, sa.year, sa.month, sa.net_wage " + "FROM t_staff s " + "LEFT JOIN t_department d ON s.dept_id = d.dept_id " + "LEFT JOIN t_salary sa ON s.staff_id = sa.staff_id " + "WHERE s.name LIKE @kw"; MySqlParameter[] ps = { new MySqlParameter("@kw", "%" + keyword + "%") }; DataTable dt = MyDB.ExecuteQuery(sql, ps); dgvData.DataSource = dt; dgvData.AutoResizeColumns(); }DataGridView.DataSource直接绑定 DataTable 是最省事的展示方式,不用手动逐行填充单元格。LEFT JOIN保证了即使某员工没发过工资,也能显示员工信息,工资字段为空。很多人会在这里踩一个坑:绑定 DataTable 之后再去改dgvData.Columns["xxx"].HeaderText,往往改不生效,因为列是自动生成的,你要么在绑定前先配置列,要么在绑定后重新赋值。这套代码里用AutoResizeColumns()让列宽自适应,但如果你喜欢自定义中文列名,记得要在绑定后手动设置:
dgvData.Columns["staff_id"].HeaderText = "员工编号"; dgvData.Columns["name"].HeaderText = "姓名";还有一个细节:@kw参数用了%通配符拼接,配合 LIKE 做模糊查询。注意这里%是加在 C# 代码里的,SQL 语句里只写LIKE @kw,如果你在 SQL 里写完LIKE '%@kw%',那查询会永远匹配不到,因为@kw被当成字面量了。这是初学者最容易翻车的地方。
5. 避坑手册:Winform 连 MySQL 最常见的 5 个翻车现场
5.1 坑 1:mysql.data.dll 加载失败
现象:编译能通过,运行程序时一执行数据库操作就报System.IO.FileNotFoundException或Could not load file or assembly 'MySql.Data'。
原因:工程引用里的 mysql.data.dll 路径失效,或者你用的是 .NET Framework 版本,但 DLL 是 .NET Core 构建的,导致运行时加载不了。
解决:右键工程 → 引用 → 检查 MySql.Data 是否存在并且未出现黄色感叹号。如果引用丢失,直接到工程目录下的packages或者bin文件夹里找到 mysql.data.dll 重新添加。如果 DLL 版本不兼容,去 MySQL 官网下载与你的 MySQL 服务端匹配的 Connector/NET 版本,解压后替换掉本地的 DLL。
5.2 坑 2:中文乱码,页面全是问号或繁体
现象:登录后看到的管理员名、部门名、员工姓名全是???,或者出现乱码。
原因:数据库连接串没带字符集,或者 hr.sql 导入时用的是 latin1 编码,又或者 MySQL 表本身的字符集就是 latin1。
解决:在连接串里明确加上CharSet=utf8;,如果还不行,用命令行检查表和库的字符集。执行ALTER DATABASE hr CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;,再对每张表执行ALTER TABLE xxx CONVERT TO CHARACTER SET utf8mb4;。改完后重启程序,重新插入数据才能验证效果。
5.3 坑 3:连接超时或 Access denied
现象:运行程序提示Unable to connect to any of the specified MySQL hosts,或者Access denied for user 'root'@'localhost'。
原因:MySQL 没启动、端口不对,或者连接串里用户名密码错误。MySQL 8.0 默认密码加密插件是caching_sha2_password,老版 mysql.data.dll 不支持这个插件,也会报认证失败。
解决:先确认 MySQL 服务在系统服务里是否启动。然后用命令行测试mysql -u root -p能不能登进去。如果账号密码没问题但程序连不上,八成是连接串里Port写错或者没写。对于 8.0 的认证问题,要么升级 mysql.data.dll,要么在 MySQL 里执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';,把认证方式改回老版本兼容的模式。
5.4 坑 4:查询结果总是差一行或者数据显示不全
现象:员工管理列表里少显示了某个员工,或者工资数据对不上。
原因:大多数情况是 JOIN 语句写错了,比如用了INNER JOIN而某个员工没有工资记录,直接被过滤掉了。也有可能是 WHERE 条件里 LIKE 参数拼写问题,导致漏数据。
解决:先看数据显示.cs 里的 SQL 是不是用了LEFT JOIN,如果用的是INNER JOIN,把没关联的过滤行丢掉。然后检查模糊查询参数里有没有多余空格,比如txtKeyword.Text.Trim()有没有写 Trim。最笨也最有效的方法是把这个 SQL 复制到 Navicat 里手动执行,比在程序里打断点定位快得多。
5.5 坑 5:修改密码后旧密码还能登录
现象:用户在「修改密码」窗口改了密码,当时提示成功,但重新登录时旧密码仍然有效。
原因:修改密码的 SQL 没有 WHERE 条件,或者条件里带了用户 ID,但缓存了旧密码。也有可能是 UPDATE 语句执行后没有 commit(MySQL 默认 autocommit 一般不会出这问题),更常见的是更新语句里字段名写错,导致实际改的是另一个字段。
解决:检查修改密码.cs 中的 SQL 语句,确认是UPDATE t_admin SET password=@new WHERE username=@user,并且传参正确。如果 SQL 没问题,在 MyDB 的 ExecuteNonQuery 方法里加一个返回受影响行数的日志,判断 UPDATE 到底改了几行。改 0 行说明用户名不对或字段错了,改 1 行才是真正成功。
6. 拿到源码后的第一件事:按这条完整链路跑通才算真正会用了
6.1 从登录到发工资,人工走一遍闭环
很多人把资源下载下来,导入工程、F5 一跑,看到登录窗口能弹出来就说“跑通了”,其实那只验证了界面。真正的跑通是一条完整业务链路:用初始管理员登录 → 建立一个部门 → 添加一个员工 → 给这个员工录一条工资 → 在数据展示里查到这条记录 → 然后退出系统。
建议按这个顺序手工验证:
| 步骤 | 操作 | 预期结果 |
|---|---|---|
| 1 | 用 hr.sql 里初始化的管理员账号登录 | 成功进入主界面 |
| 2 | 进入部门管理,新增一个部门 | 保存后列表出现新部门 |
| 3 | 进入员工管理,选择刚建的部门,添加一名员工 | 员工列表出现该员工 |
| 4 | 进入工资管理,选择这名员工,输入基本工资和奖金 | 实发工资自动计算 |
| 5 | 进入数据显示,按员工姓名搜索 | 看到员工信息和他的工资记录 |
| 6 | 退出后重新登录,尝试用错误密码 | 提示错误,用正确密码可登录 |
这一圈走下来,你才真正理解这套系统的数据流走向。如果中途哪一步断了,顺着那张表去查对应的窗体、SQL 语句、表结构,定位问题的过程就是最好的学习。尤其要留意第 4 步的实发工资是不是自动算出来的,这能看出代码里有没有把计算逻辑写在前台而不是数据库。
6.2 下一步你可以改什么
跑通之后,这套系统已经成了你的素材库。你完全可以在它的基础上做三件有价值的改造:把登录密码改成 MD5 加密存储、加一个按部门汇总工资的统计报表、把 DataGridView 换成分页控件。这些改动都能写进简历的项目描述里。
最后说个我个人习惯:接了这套代码后,我做的第一件事不是看界面,而是先看 SQL 文件里的建表语句。因为表结构决定了整个系统的边界。那次我发现t_salary表虽然有员工 ID,但缺少唯一索引,导致重复录入工资时会出现好几条记录。我把建表语句加了唯一索引,再配合代码里的ON DUPLICATE KEY UPDATE,问题就解决了。从那以后,我每次接手别人项目,都会强制先走一遍“导入 SQL → 改连接串 → 登录 → 走业务闭环”的流程,再谈其他优化。这套资源也是一样,下载下来先按这个流程跑通,它才能真正变成你自己的东西。希望帮到你。
本文还有配套的精品资源,点击获取