资讯动态

C# Winform + MySQL 人事工资管理系统:从登录到工资结算的完整实战

发布时间:2026/10/1 3:48:35 来源:尧图企业网站定制
简介基于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 MySQL2.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 Serverlocalhost;Port3306;Databasehr;Uidroot;Pwd123456;CharSetutf8;SslModenone;;这行串里的每个参数都别改错Server是 MySQL 所在主机本地跑就填localhostPort默认 3306如果你安装时改过端口就要对应改Database必须和 hr.sql 建的库名一致Uid和Pwd是你 MySQL 的账号密码CharSetutf8保证中文不乱码SslModenone让你本地调试时不走 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 usernameuser AND passwordpwd; 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_wagebase, bonusbonus, deductdeduct, net_wagenet; 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 坑 1mysql.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。解决在连接串里明确加上CharSetutf8;如果还不行用命令行检查表和库的字符集。执行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 rootlocalhost。原因MySQL 没启动、端口不对或者连接串里用户名密码错误。MySQL 8.0 默认密码加密插件是caching_sha2_password老版 mysql.data.dll 不支持这个插件也会报认证失败。解决先确认 MySQL 服务在系统服务里是否启动。然后用命令行测试mysql -u root -p能不能登进去。如果账号密码没问题但程序连不上八成是连接串里Port写错或者没写。对于 8.0 的认证问题要么升级 mysql.data.dll要么在 MySQL 里执行ALTER USER rootlocalhost 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 语句执行后没有 commitMySQL 默认 autocommit 一般不会出这问题更常见的是更新语句里字段名写错导致实际改的是另一个字段。解决检查修改密码.cs 中的 SQL 语句确认是UPDATE t_admin SET passwordnew WHERE usernameuser并且传参正确。如果 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 → 改连接串 → 登录 → 走业务闭环”的流程再谈其他优化。这套资源也是一样下载下来先按这个流程跑通它才能真正变成你自己的东西。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑