尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
C#与MySQL房屋租赁管理系统课设:数据库设计与避坑指南
简介这份资源是面向计算机相关专业在校学生的MySQL数据库课程设计完整交付包以C# WinForm实现房屋租赁管理系统涵盖房源信息、租客与管理员管理、租金账单、财务统计及系统设置等核心业务模块适合作为课设、大作业或初期项目立项的参考范例。压缩包共71个文件约12.83MB以25个cs源码文件与11个resx资源文件为主体另含sql数据库脚本、sln解决方案、csproj工程文件、doc与docx设计报告及ER图、数据流图等文档并附带MySQL连接组件安装包结构完整、层次清晰。目前已有304人学习下载。项目代码经过运行验证功能稳定配套数据库脚本与设计报告可直接对照阅读便于快速理解系统架构、数据表设计与业务逻辑实现对基础较好的读者还可在此基础上进行二次开发扩展新功能。需注意解压后路径与项目名避免使用中文以免出现解析异常。1. 从一份房屋租赁管理系统课设说起C# MySQL 到底能做出什么很多计算机专业的学生在做数据库课设时第一反应是去搜「房屋租赁管理系统源码」想找一份能跑通、能交差、还能在答辩时讲清楚逻辑的完整项目。这个方向之所以热门是因为房屋租赁业务天然适合做数据库设计房东、租客、房源、合同、租金、维修记录实体关系清晰增删改查覆盖面广还能顺带练事务和视图。用 C# 做桌面端或 Web 端配上 MySQL 做数据存储是一套成本低、资料多、上手快的组合。但真正动手后你会发现坑不在界面而在数据库表结构设计和 C# 连接层的参数处理上。这篇笔记就按「表怎么建、代码怎么写、坑怎么避」的顺序把一套可复现的房屋租赁管理系统拆开讲清楚适合正在做课设、想拿高分、或者想拿它当第一个完整项目练手的同学。2. 数据库设计先立住房屋租赁管理系统的表结构与关系2.1 五张核心表撑起整个租赁业务房屋租赁管理系统的数据库不需要花哨但必须把业务闭环跑通。我一般会先画一遍实体关系再落成表。核心实体有五个房东、租客、房源、合同、租金记录。房东和房源是一对多一个房东可以有多套房房源和合同是一对一或一对多取决于是否允许历史合同合同和租金记录是一对多一份合同按月产生多条租金流水。建表时最容易翻车的地方是字段类型和约束。比如租金金额用DECIMAL(10,2)而不是FLOAT否则对账时会出现0.30000000000000004这种玄学数字。手机号用VARCHAR(11)不要用整型否则前导零丢失。合同状态用TINYINT配合枚举注释比直接存中文更稳。-- 房源表核心字段与约束 CREATE TABLE house ( house_id INT PRIMARY KEY AUTO_INCREMENT, landlord_id INT NOT NULL, title VARCHAR(100) NOT NULL, address VARCHAR(200) NOT NULL, area DECIMAL(6,2) COMMENT 面积平方米, rent_price DECIMAL(10,2) NOT NULL COMMENT 月租金, status TINYINT DEFAULT 0 COMMENT 0待租 1已租 2下架, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_house_landlord FOREIGN KEY (landlord_id) REFERENCES landlord(landlord_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这段建表语句里DECIMAL(10,2)保证金额精确到分status用TINYINT而不是字符串是为了后续在 C# 里做状态判断时不用反复比较中文。外键约束fk_house_landlord保证不会出现没有房东的房源。utf8mb4是为了兼容租客姓名里可能出现的生僻字。参数怎么改如果课设要求支持合租房源表要拆出room子表如果要求支持历史价格rent_price不能直接改要加一张price_history表。这些扩展点答辩时老师很爱问。2.2 合同表与租金表事务和状态机是重点合同表是整个系统的中枢。它连接房源和租客同时决定租金记录的生成。合同状态一般有待生效、生效中、已到期、已终止。租金记录的状态有未付、已付、逾期。这两个状态机如果设计得随意后面 C# 代码里就会到处写if-else维护成本极高。-- 合同表状态与时间范围 CREATE TABLE contract ( contract_id INT PRIMARY KEY AUTO_INCREMENT, house_id INT NOT NULL, tenant_id INT NOT NULL, start_date DATE NOT NULL, end_date DATE NOT NULL, monthly_rent DECIMAL(10,2) NOT NULL, deposit DECIMAL(10,2) NOT NULL, status TINYINT DEFAULT 0 COMMENT 0待生效 1生效中 2已到期 3已终止, sign_date DATETIME DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_contract_house FOREIGN KEY (house_id) REFERENCES house(house_id), CONSTRAINT fk_contract_tenant FOREIGN KEY (tenant_id) REFERENCES tenant(tenant_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里start_date和end_date用DATE而不是DATETIME因为租赁按天算不按秒算。monthly_rent单独存一份而不是每次去查房源表是为了防止房东改价后历史合同金额被篡改。这是血泪经验很多课设为了「范式」把租金只存在房源表结果合同一签完房东一改价所有历史合同金额全变对账直接崩。租金记录表建议在合同生效时由程序批量生成而不是等收款时才插入。这样逾期查询只需要扫rent_record表不用做复杂的日期推算。-- 租金记录表按月生成 CREATE TABLE rent_record ( record_id INT PRIMARY KEY AUTO_INCREMENT, contract_id INT NOT NULL, period VARCHAR(7) NOT NULL COMMENT 账期格式2024-06, amount DECIMAL(10,2) NOT NULL, pay_status TINYINT DEFAULT 0 COMMENT 0未付 1已付 2逾期, pay_date DATETIME NULL, CONSTRAINT fk_rent_contract FOREIGN KEY (contract_id) REFERENCES contract(contract_id), UNIQUE KEY uk_contract_period (contract_id, period) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;UNIQUE KEY uk_contract_period是后悔药防止同一份合同同一个月生成两条租金记录。没有这个约束程序里稍微写错循环边界就会重复插入月底对账时多出一倍金额。3. C# 连接 MySQL从安装配置到增删改查落地3.1 环境准备MySQL 安装与 C# 驱动选择在 Windows 10 上装 MySQL常见做法是下mysql-installer-community选 Server only 或 Custom端口默认 3306。安装过程中会要求设 root 密码建议设一个自己记得住的课设环境不用追求复杂。装完后用mysql -u root -p能进去就说明服务正常。如果 3306 被占用改端口后记得在 C# 连接字符串里同步改。C# 连 MySQL 的驱动主流是MySql.Data或MySqlConnector。课设里我用MySqlConnector多一些因为它对异步支持更好而且 NuGet 安装干净。在 Visual Studio 里右键项目 → 管理 NuGet 程序包 → 搜索MySqlConnector→ 安装。不要用那种来路不明的「绿色版 DLL」版本对不上会报TypeInitializationException排查半天。连接字符串一般长这样// 连接字符串按实际环境改 server、port、database、uid、pwd string connStr serverlocalhost;port3306;databasehouse_rental;uidroot;pwd你的密码;CharSetutf8mb4;;CharSetutf8mb4必须加否则中文姓名和地址会变问号。SslMode在课设本地环境可以设为None避免证书报错。3.2 封装一个可复用的数据库访问层直接在窗体代码里写MySqlConnection是课设最常见翻车点连接没关、异常没捕、SQL 拼接被注入。我一般会封一个DbHelper类把连接、执行、查询三件事收口。using MySqlConnector; using System.Data; public static class DbHelper { private static readonly string ConnStr serverlocalhost;port3306;databasehouse_rental;uidroot;pwd你的密码;CharSetutf8mb4;SslModeNone;; // 执行增删改返回受影响行数 public static int Execute(string sql, params MySqlParameter[] parameters) { using var conn new MySqlConnection(ConnStr); using var cmd new MySqlCommand(sql, conn); if (parameters ! null) cmd.Parameters.AddRange(parameters); conn.Open(); return cmd.ExecuteNonQuery(); } // 查询返回 DataTable方便绑定 DataGridView public static DataTable Query(string sql, params MySqlParameter[] parameters) { using var conn new MySqlConnection(ConnStr); using var cmd new MySqlCommand(sql, conn); if (parameters ! null) cmd.Parameters.AddRange(parameters); var adapter new MySqlDataAdapter(cmd); var table new DataTable(); adapter.Fill(table); return table; } }using var保证连接和命令对象在方法结束时自动释放不用手动写try-finally。params MySqlParameter[]让调用方可以传零个或多个参数配合参数化查询防注入。Query返回DataTable是为了直接绑到DataGridView课设演示时最省事。参数说明Execute适合INSERT、UPDATE、DELETEQuery适合SELECT。如果要做事务比如签合同同时改房源状态和插合同记录需要再封一个带MySqlTransaction的方法不能直接用上面这两个。3.3 增删改查的四个典型调用房源列表查询按状态筛选// 查询待租房源status0 string sql SELECT house_id, title, address, rent_price FROM house WHERE status status; DataTable dt DbHelper.Query(sql, new MySqlParameter(status, 0)); dataGridView1.DataSource dt;这里用status占位而不是字符串拼接WHERE status 0。虽然 0 是整数看起来安全但养成参数化习惯后遇到用户输入的搜索关键词就不会翻车。新增租客string sql INSERT INTO tenant (name, phone, id_card) VALUES (name, phone, idCard); int rows DbHelper.Execute(sql, new MySqlParameter(name, txtName.Text.Trim()), new MySqlParameter(phone, txtPhone.Text.Trim()), new MySqlParameter(idCard, txtIdCard.Text.Trim())); if (rows 0) MessageBox.Show(新增失败);Trim()去掉前后空格避免用户复制粘贴时带入不可见字符。rows 0判断虽然简单但能拦住一部分静默失败。更新房源租金string sql UPDATE house SET rent_price price WHERE house_id id; DbHelper.Execute(sql, new MySqlParameter(price, decimal.Parse(txtPrice.Text)), new MySqlParameter(id, houseId));decimal.Parse如果用户输入非数字会抛FormatException所以外面要包try-catch或用decimal.TryParse。这是课设答辩时老师常问的「你怎么处理非法输入」。删除合同前先检查租金记录string checkSql SELECT COUNT(*) FROM rent_record WHERE contract_id id AND pay_status 0; DataTable dt DbHelper.Query(checkSql, new MySqlParameter(id, contractId)); if (Convert.ToInt32(dt.Rows[0][0]) 0) { MessageBox.Show(存在未付租金不能删除合同); return; }这段逻辑是业务规则不是数据库约束。放在 C# 层做是为了给用户明确提示。如果只靠外键ON DELETE CASCADE删合同会连带删掉未付租金记录财务上说不清。4. 避坑与排查课设里最容易翻车的五个地方4.1 中文乱码现象是 DataGridView 显示问号现象插入中文姓名后数据库里查出来是???或者 C# 界面显示乱码。原因通常是三处字符集不统一MySQL 服务端默认latin1、建表时没指定utf8mb4、连接字符串没写CharSetutf8mb4。解决先SHOW VARIABLES LIKE character%;确认服务端字符集再检查表和连接字符串。最稳的做法是建库时就写CREATE DATABASE house_rental DEFAULT CHARSET utf8mb4;连接字符串加CharSetutf8mb4。4.2 连接未关闭程序跑一会儿就报 Too many connections现象反复打开窗体查询后MySQL 报Too many connections。原因是在循环或频繁调用的方法里new MySqlConnection后没有Dispose。解决统一用using包裹或者用DbHelper收口。如果已经写散了把每个conn.Open()后面都补上using或try-finally。课设演示时间短可能看不出来但答辩时老师让你连续点十次查询就可能当场翻车。4.3 日期格式C# 的 DateTime 和 MySQL 的 DATE 对不上现象插入合同开始日期时报Incorrect date value。原因是 C# 的DateTime.ToString()默认带时间或者用了yyyy/MM/dd而 MySQL 期望yyyy-MM-dd。解决参数化时直接传DateTime对象让驱动处理格式如果非要传字符串用ToString(yyyy-MM-dd)。查询时比较日期范围用BETWEEN start AND end不要用字符串拼接。4.4 主键冲突自增 ID 被手动插入打乱现象新增记录时报Duplicate entry for key PRIMARY KEY。原因是之前手动INSERT时指定了house_id导致AUTO_INCREMENT计数器没跟上。解决课设里尽量不要手动指定自增主键。如果已经乱了用ALTER TABLE house AUTO_INCREMENT 最大值1;修正。更彻底的办法是删掉测试数据重新建表。4.5 事务未提交签合同后房源状态没变现象签合同代码里先插合同、再改房源状态结果合同有了房源还是「待租」。原因是两条 SQL 分别用了独立连接第一条成功第二条失败或者没包事务。解决把两条操作放进同一个MySqlConnection和MySqlTransaction要么都提交要么都回滚。课设里至少要把「签合同」这个核心业务做成事务答辩时能讲清楚 ACID 里的原子性。5. 进阶技巧用视图和存储过程把课设做出区分度课设拿高分的关键往往不是界面多漂亮而是数据库层有没有「超出增删改查」的东西。我一般会加两个视图和一个存储过程代码量不大但答辩时能讲出设计意图。第一个视图房源完整信息把房东姓名、当前合同状态拼在一起省去 C# 里多次查询。CREATE VIEW v_house_detail AS SELECT h.house_id, h.title, h.address, h.rent_price, h.status, l.name AS landlord_name, l.phone AS landlord_phone, c.contract_id, c.end_date FROM house h LEFT JOIN landlord l ON h.landlord_id l.landlord_id LEFT JOIN contract c ON h.house_id c.house_id AND c.status 1;LEFT JOIN保证没有合同的房源也能显示。c.status 1只关联生效中的合同避免历史合同干扰。第二个视图逾期租金清单直接给财务页面用。CREATE VIEW v_overdue_rent AS SELECT r.record_id, t.name AS tenant_name, h.title AS house_title, r.period, r.amount, r.pay_status FROM rent_record r JOIN contract c ON r.contract_id c.contract_id JOIN tenant t ON c.tenant_id t.tenant_id JOIN house h ON c.house_id h.house_id WHERE r.pay_status 2 OR (r.pay_status 0 AND r.period DATE_FORMAT(CURDATE(), %Y-%m));这个视图把「已标记逾期」和「未标记但账期已过」两种情况都算进去避免只依赖程序定时更新状态。存储过程按月生成租金记录。签合同时调用一次传入合同 ID 和起止日期自动算出每个月一条。DELIMITER // CREATE PROCEDURE sp_generate_rent(IN p_contract_id INT, IN p_start DATE, IN p_end DATE) BEGIN DECLARE cur DATE DEFAULT p_start; WHILE cur p_end DO INSERT IGNORE INTO rent_record (contract_id, period, amount, pay_status) SELECT p_contract_id, DATE_FORMAT(cur, %Y-%m), monthly_rent, 0 FROM contract WHERE contract_id p_contract_id; SET cur DATE_ADD(cur, INTERVAL 1 MONTH); END WHILE; END // DELIMITER ;INSERT IGNORE配合uk_contract_period唯一键重复调用不会产生重复记录。WHILE cur p_end保证不会生成超出合同期的账期。C# 里调用using var conn new MySqlConnection(ConnStr); using var cmd new MySqlCommand(sp_generate_rent, conn) { CommandType CommandType.StoredProcedure }; cmd.Parameters.AddWithValue(p_contract_id, contractId); cmd.Parameters.AddWithValue(p_start, startDate); cmd.Parameters.AddWithValue(p_end, endDate); conn.Open(); cmd.ExecuteNonQuery();CommandType.StoredProcedure告诉驱动这是存储过程不是普通 SQL。参数名要和存储过程定义一致大小写不敏感但建议统一。验证方法签一份 6 个月的合同调用存储过程后查rent_record应该正好 6 条账期从起始月到结束前一个月。如果多一条或少一条检查WHILE边界和DATE_ADD的月份进位。我自己的习惯是每次改完存储过程先用CALL sp_generate_rent(1, 2024-01-01, 2024-07-01);在 MySQL 命令行里跑一遍确认结果再接到 C# 里。这样能把数据库层和界面层的问题分开省得两边一起查。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

rea缩写全解析:read-eval-apply、响应式事件架构与资源效率分析实战

rea缩写全解析:read-eval-apply、响应式事件架构与资源效率分析实战

1. 从一个字母说起:为什么"rea"值得单独拿出来聊第一次看到"rea"这个标题,我脑子里蹦出来的第一个念头是——这大概率是个缩写,而且是个被严重低估的缩写。在技术圈里混久了你会发现,越是短的东西&#xff0c…

📅 2026/10/10 13:52:12
风光储互补调度:Matlab下电池与废弃矿井抽蓄的多元储能优化建模

风光储互补调度:Matlab下电池与废弃矿井抽蓄的多元储能优化建模

做新能源调度,绕不开一个尴尬的现象:独立看风电、光伏的预测曲线都还行,但把它们放进同一个系统里,要么白天光伏功率顶着天、晚上风机疯转,负荷侧却跟不上;要么连续几天阴雨无风,电池耗尽&#…

📅 2026/10/10 13:52:12
使用 Apache Beam 进行 AI/ML 数据探索与数据预处理流水线开发

使用 Apache Beam 进行 AI/ML 数据探索与数据预处理流水线开发

大数据批处理流处理数据工程 【免费下载链接】beam Apache Beam is a unified programming model for Batch and Streaming data processing. 项目地址: https://gitcode.com/gh_mirrors/beam4/beam 点击查看 免费下载 Apache Beam 为 AI/ML 项目提供了一套统一的数…

📅 2026/10/10 13:52:12
MORE NEWS

更多资讯

📰

Token是什么?NLP、认证、区块链、编译器中的四种含义与边界

第一次被Token这个词搞懵,是某次和同事调试一个跨平台系统。前端同事说Token过期了需要重新登录,算法同事说这段文本Token切得太多,后端同事说Token里的权限信息没带全。三个人用的都是同一个英文单词,但谁也没接住谁的话。那时候…

📰

豆瓣评论情感分析实战:SnowNLP清洗、校准与TF-IDF词云

简介:本资源是一份面向Python初学者与数据挖掘入门者的实战教学材料,聚焦豆瓣电影《肖申克救赎》评论文本的情感分析与可视化任务,通过调用轻量级中文NLP库SnowNLP实现情感倾向判断与词云生成,适用于课程实验、小规模文本分析项目…

📰

专科生论文降AI率实战指南:检测原理与9个工具组合用法

专科生写论文最怕什么?怕AI率。我见过太多同学,用DeepSeek或者豆包生成一段内容,复制粘贴进Word,交上去之后被AIGC检测拦下来,直接退回重写。有些更严重的,被老师约谈,说不清楚就按学术不端处理…

📰

并查集与贪心:破解情侣牵手的最小交换次数

1. 初见765:贪心能过,但我被"为什么正确"问住了我刷并查集(union-find)专项题单时,最先遇到的都是一批"给一堆连接关系,问连通块有几个"的直白题目。直到碰见力扣765情侣牵手&#xff…

📰

重言式判别程序设计:从表达式树到真值表的完整实现

简介:本资源是一份面向计算机专业本科生的数据结构课程设计实践材料,聚焦重言式(逻辑恒等式)的程序化判别实现,解决布尔表达式真值恒定性验证这一典型算法与数据结构综合应用问题。压缩包共4个文件,含2份Wo…

📰

用Python从零复现KCF目标跟踪算法:原理、实现与避坑指南

简介:KCF用Python代码复现.rar是一份基于Python实现的KCF(核相关滤波)目标跟踪算法复现工程,适合计算机视觉入门者、算法复现爱好者以及需要快速搭建跟踪demo的研究人员。压缩包采用rar格式,内含KCFpy-master项目&…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬