【实战指南】C#与ADO.NET:构建图书管理系统从界面到数据库

发布时间:2026/7/5 13:24:48

【实战指南】C#与ADO.NET:构建图书管理系统从界面到数据库 1. 环境准备与项目创建在开始构建图书管理系统之前我们需要准备好开发环境。首先确保已安装Visual Studio 2022社区版即可和SQL Server Express。打开Visual Studio后选择新建项目在模板中选择Windows窗体应用(.NET Framework)命名为BookManagementSystem。我习惯在解决方案资源管理器中先创建三个文件夹Models存放数据模型类DAL数据访问层UI用户界面相关文件接下来需要安装必要的NuGet包。右键项目选择管理NuGet程序包搜索并安装Microsoft.Data.SqlClient最新的ADO.NET提供程序System.Data.DataSetExtensions用于数据绑定提示如果使用SQL Server身份验证而非Windows身份验证连接字符串需要包含用户名和密码。生产环境中建议将连接字符串加密存储在配置文件中。2. 数据库设计与建表图书管理系统的核心是数据库设计。打开SQL Server Management Studio新建名为BookDB的数据库。我们需要创建三张基础表-- 管理员表 CREATE TABLE t_admin ( id VARCHAR(20) PRIMARY KEY, psw VARCHAR(50) NOT NULL ); -- 图书表 CREATE TABLE t_book ( isbn VARCHAR(20) PRIMARY KEY, name NVARCHAR(100) NOT NULL, author NVARCHAR(50), publisher NVARCHAR(100), stock INT DEFAULT 0 ); -- 借阅记录表 CREATE TABLE t_lend ( id INT IDENTITY(1,1) PRIMARY KEY, user_id VARCHAR(20) NOT NULL, book_isbn VARCHAR(20) NOT NULL, lend_date DATETIME DEFAULT GETDATE(), return_date DATETIME, FOREIGN KEY (book_isbn) REFERENCES t_book(isbn) );实测中发现几个常见问题需要注意ISBN字段长度应根据实际需求设置国际标准是13位图书名称和作者字段建议使用NVARCHAR以支持中文借阅记录的归还日期应为NULL表示未归还3. ADO.NET核心数据访问层在DAL文件夹中创建Dao.cs这是整个系统的数据库操作核心。我采用单例模式来管理数据库连接using Microsoft.Data.SqlClient; using System.Configuration; namespace BookMS.DAL { public class Dao { private static SqlConnection _connection; private static readonly string _connStr ConfigurationManager.ConnectionStrings[BookDB].ConnectionString; private Dao() { } public static SqlConnection GetConnection() { if (_connection null) { _connection new SqlConnection(_connStr); _connection.Open(); } else if (_connection.State System.Data.ConnectionState.Closed) { _connection.Open(); } return _connection; } public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters) { using (var cmd new SqlCommand(sql, GetConnection())) { cmd.Parameters.AddRange(parameters); return cmd.ExecuteNonQuery(); } } public static SqlDataReader ExecuteReader(string sql, params SqlParameter[] parameters) { var cmd new SqlCommand(sql, GetConnection()); cmd.Parameters.AddRange(parameters); return cmd.ExecuteReader(); } } }踩过的坑早期版本没有妥善处理连接关闭问题导致连接池耗尽。后来改用using语句确保资源释放关键业务操作使用事务public static bool ExecuteTransaction(params SqlCommand[] commands) { using (var transaction GetConnection().BeginTransaction()) { try { foreach (var cmd in commands) { cmd.Connection GetConnection(); cmd.Transaction transaction; cmd.ExecuteNonQuery(); } transaction.Commit(); return true; } catch { transaction.Rollback(); throw; } } }4. 登录模块实现登录界面需要区分管理员和普通用户。在UI文件夹中添加Login窗体包含两个TextBox用户名和密码两个RadioButton用户类型选择一个Button登录核心登录逻辑private void btnLogin_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtUser.Text) || string.IsNullOrEmpty(txtPwd.Text)) { MessageBox.Show(用户名或密码不能为空); return; } string tableName radioAdmin.Checked ? t_admin : t_user; string sql $SELECT * FROM {tableName} WHERE idid AND pswpsw; var parameters new[] { new SqlParameter(id, txtUser.Text), new SqlParameter(psw, txtPwd.Text) // 实际项目应该加密 }; using (var reader Dao.ExecuteReader(sql, parameters)) { if (reader.Read()) { Data.UID reader[id].ToString(); Data.UName reader[name]?.ToString(); var mainForm radioAdmin.Checked ? (Form)new AdminMainForm() : new UserMainForm(); this.Hide(); mainForm.ShowDialog(); this.Show(); } else { MessageBox.Show(登录失败请检查凭证); } } }安全提示实际项目中密码应该使用哈希加盐存储SQL语句要参数化防止注入。我曾在早期版本直接拼接SQL字符串结果被测试人员轻松注入这个教训很深刻。5. 图书管理模块开发管理员界面主要包含DataGridView显示图书列表以及增删改查功能。先创建AdminMainForm添加MenuStrip控件设置菜单项。图书管理窗体(AdminBookForm)的关键代码public partial class AdminBookForm : Form { private BindingSource _bindingSource new BindingSource(); public AdminBookForm() { InitializeComponent(); dgvBooks.AutoGenerateColumns false; LoadBooks(); } private void LoadBooks() { string sql SELECT isbn, name, author, publisher, stock FROM t_book; var adapter new SqlDataAdapter(sql, Dao.GetConnection()); var dataSet new DataSet(); adapter.Fill(dataSet, Books); _bindingSource.DataSource dataSet.Tables[Books]; dgvBooks.DataSource _bindingSource; } private void btnAdd_Click(object sender, EventArgs e) { var form new BookEditForm(); if (form.ShowDialog() DialogResult.OK) { string sql INSERT INTO t_book VALUES (isbn, name, author, publisher, stock); var parameters new[] { new SqlParameter(isbn, form.ISBN), // 其他参数... }; if (Dao.ExecuteNonQuery(sql, parameters) 0) { MessageBox.Show(添加成功); LoadBooks(); } } } }数据绑定技巧设置DataGridView的AutoGenerateColumns为false手动配置列与数据字段的映射关系。这样能精确控制显示格式private void ConfigureDataGridView() { dgvBooks.Columns.Add(new DataGridViewTextBoxColumn() { DataPropertyName isbn, HeaderText ISBN, Width 150 }); // 其他列配置... }6. 借阅功能实现用户界面需要实现图书查询和借阅功能。在UserMainForm中添加搜索面板和图书列表private void btnSearch_Click(object sender, EventArgs e) { string keyword % txtKeyword.Text %; string sql SELECT * FROM t_book WHERE name LIKE keyword OR author LIKE keyword; var adapter new SqlDataAdapter(sql, Dao.GetConnection()); adapter.SelectCommand.Parameters.AddWithValue(keyword, keyword); var table new DataTable(); adapter.Fill(table); dgvBooks.DataSource table; } private void btnBorrow_Click(object sender, EventArgs e) { if (dgvBooks.CurrentRow null) return; string isbn dgvBooks.CurrentRow.Cells[isbn].Value.ToString(); string sql INSERT INTO t_lend (user_id, book_isbn) VALUES (uid, isbn); var parameters new[] { new SqlParameter(uid, Data.UID), new SqlParameter(isbn, isbn) }; try { if (Dao.ExecuteNonQuery(sql, parameters) 0) { MessageBox.Show(借阅成功); } } catch (SqlException ex) { if (ex.Number 547) // 外键约束错误 MessageBox.Show(图书不存在); else throw; } }性能优化点当图书数据量大时应该实现分页查询而不是一次性加载所有数据。可以使用ROW_NUMBER()实现分页WITH BookPage AS ( SELECT ROW_NUMBER() OVER (ORDER BY name) AS RowNum, * FROM t_book WHERE name LIKE keyword ) SELECT * FROM BookPage WHERE RowNum BETWEEN start AND end7. 报表与统计功能管理员通常需要查看借阅统计。我们可以使用Chart控件可视化数据private void LoadStats() { string sql SELECT b.name, COUNT(l.id) AS lend_count FROM t_book b LEFT JOIN t_lend l ON b.isbn l.book_isbn GROUP BY b.name ORDER BY lend_count DESC; var adapter new SqlDataAdapter(sql, Dao.GetConnection()); var dataSet new DataSet(); adapter.Fill(dataSet); chart1.Series[Series1].Points.DataBind( dataSet.Tables[0].DefaultView, name, lend_count, ); }对于复杂报表我推荐使用ReportViewer控件或第三方报表工具如DevExpress。曾经一个项目需要导出Excel报表直接用DataTable导出性能很差后来改用ClosedXML库效率提升明显。8. 系统部署与维护完成开发后需要准备安装包。在Visual Studio中添加安装项目包含主程序文件.NET Framework运行环境如果目标机器没有数据库脚本配置文件模板数据库部署建议准备SQL脚本创建数据库和表包含初始数据插入脚本如管理员账户考虑添加数据库升级脚本维护技巧在app.config中配置连接字符串时可以使用配置文件转换功能为不同环境开发/测试/生产设置不同的连接字符串connectionStrings add nameBookDB connectionString... providerNameSystem.Data.SqlClient / /connectionStrings日志记录建议使用log4net记录系统操作日志和异常便于故障排查。我在Dao类中添加了日志记录后排查数据库问题效率提高了许多。

相关新闻