C# WinForm实现图书管理系统:三层架构与完整代码示例
本文将展示如何利用C#语言和WinForm框架开发一套具备注册、查询、借阅、归还及欠费管理功能的图书管理系统。内容涵盖基于SQL Server的数据库结构设计、三层架构(表示层、业务逻辑层、数据访问层)的代码组织方式,以及关键界面的核心逻辑实现。
系统概述与设计思路
本示例旨在通过模拟真实的图书馆业务场景,帮助理解桌面应用程序与后端数据库的交互机制。系统主要支持两类用户操作:
- 学生/读者端:账号注册、馆藏图书查询、借书、还书、查看借阅记录及欠费金额查询。
- 管理员端:通常用于后台管理(本示例重点展示读者端业务流程)。
为了保持代码结构的清晰与可维护性,系统采用经典的三层架构进行分层设计:
- 表示层 (Presentation Layer):负责界面显示与用户交互(WinForm窗体)。
- 业务逻辑层 (Business Logic Layer):处理核心业务规则(如借书判断、欠费计算)。
- 数据访问层 (Data Access Layer):封装对SQL Server数据库的连接、执行SQL语句及结果集获取操作。
数据库环境准备
在开始编码前,需要在SQL Server中创建基础数据结构。以下是创建数据库及五张核心表的完整脚本,并预置了测试数据供调试使用。
第1步:创建数据库与核心表结构
运行以下SQL脚本以初始化环境。注意修改文件路径以适应本地环境。
create database MyLibrary
on
(name=Mylibrary_data1,
filename='d:\Mylibrary_data1.mdf',
size=10,
maxsize=50,
filegrowth=4)
log on
(name=Mylibrary_log1,
filename='d:\Mylibrary_log1.ldf',
size=10MB,
maxsize=20MB,
filegrowth=2MB);
use MyLibrary;
-- 读者表
create table reader(
readerid varchar(20) primary key,
readername varchar(20) not null,
readersex varchar(20) not null,
readertype varchar(20) not null,
readerpd varchar(20) not null
);
-- 图书表
create table book(
bookid varchar(20) primary key,
booktype varchar(20) not null,
bookauthor varchar(20) not null,
bookname varchar(20) not null,
isbrrowed varchar(20) not null,
booklibrary varchar(20) not null,
bookpubdate datetime
);
-- 借阅记录表
create table brrow_data(
readerid varchar(20) primary key,
bookid varchar(20),
bookname varchar(20),
brrowdate datetime,
foreign key (readerid) references reader(readerid),
foreign key (bookid) references book(bookid)
);
-- 归还记录表
create table return_record(
readerid varchar(20) primary key,
bookid varchar(20),
bookname varchar(20),
returndate datetime,
foreign key (readerid) references reader(readerid),
foreign key (bookid) references book(bookid)
);
-- 欠费信息表
create table readerfee(
readerid varchar(20) primary key,
bookid varchar(20),
bookname varchar(20),
readerpay varchar(20),
foreign key (readerid) references reader(readerid),
foreign key (bookid) references book(bookid)
);
-- 插入测试数据(图书)
insert into book values ('3140921000','缥缈之旅','修真','小猪','仙王出版社','2005-09-01','否');
insert into book values ('3140921001','唐朝好男人','穿越','多一半','新星出版社','2005-07-01','否');
insert into book values ('3140921002','鬼吹灯','恐怖','天下霸唱','安徽文艺出版社','2005-09-01','否');
insert into book values ('3140921003','和空姐同居的日子','都市','海王','中国海关出版社','2005-08-01','否');
insert into book values ('3140921004','卡图','科幻','方向','广西人民出版社','2005-06-01','否');
insert into book values ('3140921005','蜀山剑侠传','仙侠','还珠楼主','陕西人民出版社','2005-04-01','否');
insert into book values ('3140921006','何以笙箫默','言情','顾漫','朝华出版社','2005-05-01','否');
insert into book values ('3140921007','步步惊心','穿越','童话','民族出版社','2005-12-01','否');
-- 插入测试数据(读者)
insert into reader values ('21007000','李磊','男','学生','000000');
insert into reader values ('21007001','棠张僧','男','学生','000000');
insert into reader values ('21007002','韩梅梅','女','学生','000000');
insert into reader values ('21007003','路西','女','学生','000000');
insert into reader values ('21007004','王强','男','学生','000000');
insert into reader values ('21007005','马正标','男','管理','000000');
insert into reader values ('21007006','卢海鹏','男','管理','000000');
insert into reader values ('21007007','李艳玲','女','管理','000000');客户端界面与核心逻辑实现
第1步:登录模块开发
登录界面是系统的入口,主要负责验证用户身份并跳转至对应权限的界面。实际生产中建议使用参数化查询防止SQL注入,此处为教学目的展示基本逻辑。
登录界面布局示意:
登录按钮与连接初始化核心代码:
using System;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Library
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// 简单演示:点击登录后直接进入学生主界面(省略了详细的密码校验逻辑,实际应用需补充)
Form2 form2 = new Form2();
this.Hide();
form2.Show();
mycon.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
// 建立数据库连接配置
string con = "Server=.;Database=MyLibrary;Trusted_Connection=SSPI";
mycon = new SqlConnection(con);
mycon.Open();
}
private void button2_Click(object sender, EventArgs e)
{
Form3 form3 = new Form3();
this.Hide();
form3.Show();
}
}
}第2步:新用户注册逻辑
注册页面用于新增读者账号,包含基本的非空校验和重复账号检测。
注册界面布局示意:
注册提交事件代码:
using System;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Library
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// 检查账号是否已存在
string sql = string.Format("select count(*) from reader where readerid='{0}'", textBox1.Text);
SqlCommand com = new SqlCommand(sql, mycon);
int count = (int)com.ExecuteScalar();
if (count == 1)
{
MessageBox.Show("抱歉,该账号已存在!");
}
else
{
// 检查必填字段是否为空
if (textBox1.Text=="" || textBox2.Text=="" || textBox4.Text=="" || comboBox1.Text=="" || textBox3.Text=="")
{
MessageBox.Show("请将信息填写完整!");
}
else
{
// 此处应添加 INSERT INTO reader ... 实际写入代码
MessageBox.Show("注册成功!请返回登录。");
Form1 form1 = new Form1();
form1.Show();
this.Hide();
}
}
}
private void Form3_Load(object sender, EventArgs e)
{
string con = "Server=.;Database=MyLibrary;Trusted_Connection=SSPI";
mycon = new SqlConnection(con);
mycon.Open();
}
}
}第3步:学生主界面功能实现
这是系统的核心区域,包含个人信息查看、图书检索、借还操作及欠费缴纳等功能。
学生管理主界面示意:
主要功能代码逻辑:
- 数据查询:利用
SqlDataAdapter填充DataSet并绑定至DataGridView。 - 借书逻辑:输入书名 -> 查询是否存在 -> 插入借阅记录表。
- 还书逻辑:输入书号 -> 确认借阅状态 -> 插入归还记录 -> 删除借阅记录。
- 欠费计算:根据当前日期与借出日期的差值,超过30天部分按每天0.3元累计。
核心操作事件代码:
using System;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
namespace Library
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public string readerid; // 当前登录用户的ID
string sql, con;
SqlConnection mycon;
SqlCommand com;
private void Form2_Load(object sender, EventArgs e)
{
// 初始化界面隐藏项
label1.Hide(); textBox1.Hide(); button4.Hide();
dataGridView1.Hide();
con = "Server=.;Database=MyLibrary;Trusted_Connection=SSPI";
mycon = new SqlConnection(con);
mycon.Open();
}
// 查看个人信息
private void button1_Click(object sender, EventArgs e)
{
dataGridView1.Show();
sql = string.Format("select * from reader where readerid='{0}'", readerid);
LoadData(sql);
}
// 查看所有图书
private void button2_Click(object sender, EventArgs e)
{
dataGridView1.Show();
sql = "select * from book";
LoadData(sql);
}
// 缴缴费功能
private void button3_Click(object sender, EventArgs e)
{
try
{
// 计算超期罚款逻辑:超过30天,每天0.3元
string calcSql = string.Format(
"insert into readerfee(readerid,bookid,bookname,readerpay) select readerid ,bookid , bookname,
0.03*(datediff(day,convert(smalldatetime,brrowdate),getdate())-30)
from brrow_data where datediff(day,convert(smalldatetime,brrowdate),getdate())>=0;");
com = new SqlCommand(calcSql, mycon);
com.ExecuteNonQuery();
}
catch { }
// 显示当前用户的费用列表
string querySql = string.Format("select * from readerfee where readerid='{0}'", readerid);
LoadData(querySql);
}
// 借书/还书切换菜单响应
private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)
{
dataGridView1.Hide();
if (comboBox2.Text == "我要借书")
{
button4.Show();
button4.Text = "借阅本书";
label1.Text = "搜索书名";
label1.Show();
textBox1.Show();
}
else if (comboBox2.Text == "我要还书")
{
button4.Show();
button4.Text = "归还本书";
label1.Text = "所借书号";
label1.Show();
textBox1.Show();
}
}
// 执行借书或还书操作
private void button4_Click(object sender, EventArgs e)
{
if (button4.Text == "借阅本书")
{
// 1. 检查图书是否存在
sql = string.Format("select count(*) from book where bookname='{0}'", textBox1.Text);
com = new SqlCommand(sql, mycon);
int count = (int)com.ExecuteScalar();
if (count >= 1)
{
// 2. 获取BookId
sql = string.Format("select bookid from book where bookname='{0}'", textBox1.Text);
com = new SqlCommand(sql, mycon);
string bookid = (string)com.ExecuteScalar();
// 3. 插入借阅记录
sql = string.Format("insert into brrow_data (readerid,bookid,bookname,brrowdate) values('{0}','{1}','{2}','{3}')",
readerid, bookid, textBox1.Text, DateTime.Now);
com = new SqlCommand(sql, mycon);
com.ExecuteNonQuery();
MessageBox.Show("借书成功!");
}
else
{
MessageBox.Show("抱歉,不存在本书!");
}
}
else if (button4.Text == "归还本书")
{
// 1. 检查是否存在未还记录
sql = string.Format("select count(*) from brrow_data where bookid='{0}'", textBox1.Text);
com = new SqlCommand(sql, mycon);
int count = (int)com.ExecuteScalar();
if (count >= 1)
{
// 2. 获取书名用于记录
sql = string.Format("select bookname from brrow_data where bookid='{0}'", textBox1.Text);
com = new SqlCommand(sql, mycon);
string bookname = (string)com.ExecuteScalar();
// 3. 插入归还记录
sql = string.Format("insert into return_record(readerid,bookid,bookname,returndate) values ('{0}','{1}','{2}','{3}')",
readerid, textBox1.Text, bookname, DateTime.Now);
com = new SqlCommand(sql, mycon);
com.ExecuteNonQuery();
// 4. 清除借阅记录
sql = string.Format("delete from brrow_data where bookid='{0}'", textBox1.Text);
com = new SqlCommand(sql, mycon);
com.ExecuteNonQuery();
MessageBox.Show(bookname + " 还书成功!");
}
else
{
MessageBox.Show("抱歉!您没有借这本书!");
}
}
}
// 辅助方法:加载数据到 DataGridView
private void LoadData(string querySql)
{
SqlDataAdapter mydata = new SqlDataAdapter(querySql, con);
DataSet myds = new DataSet();
mydata.Fill(myds, "result");
dataGridView1.DataSource = myds.Tables[0];
}
}
}总结与维护建议
通过上述步骤,我们实现了一个基础的图书管理系统原型。该系统展示了如何从底层数据库设计到上层UI交互的完整开发流。在实际生产环境中,建议在以下几个方向进行优化:
- 安全性:原文中的字符串拼接SQL容易遭受SQL注入攻击,强烈建议全面替换为
SqlParameter参数化查询。 - 架构分离:目前的代码将所有逻辑写在WinForm中,实际项目应将数据库操作移至DAL,将计费等业务规则移至BLL,保持代码整洁。
- 异常处理:增加更细致的Try-Catch块,捕获具体的SQL错误或网络断开情况,并向用户反馈友好的错误信息。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









