C# 图书管理系统(三层架构)

简介: C#三层架构图书管理系统,包含表示层、业务逻辑层和数据访问层。

C#三层架构图书管理系统,包含表示层、业务逻辑层和数据访问层。

系统架构设计

1. 项目结构

BookManagementSystem/
├── BookManagementSystem.Model/          (实体层)
├── BookManagementSystem.DAL/           (数据访问层)
├── BookManagementSystem.BLL/           (业务逻辑层)
├── BookManagementSystem.UI/            (表示层 - WinForm)
└── BookManagementSystem.UnitTest/      (单元测试)

2. 核心代码实现

2.1 Model层 - 实体类

Book.cs

namespace BookManagementSystem.Model
{
   
    /// <summary>
    /// 图书实体类
    /// </summary>
    public class Book
    {
   
        public int Id {
    get; set; }
        public string ISBN {
    get; set; }
        public string Title {
    get; set; }
        public string Author {
    get; set; }
        public string Publisher {
    get; set; }
        public DateTime PublishDate {
    get; set; }
        public string Category {
    get; set; }
        public decimal Price {
    get; set; }
        public int Stock {
    get; set; }  // 库存数量
        public int AvailableStock {
    get; set; }  // 可借数量
        public DateTime CreateTime {
    get; set; }
        public DateTime UpdateTime {
    get; set; }
    }
}

User.cs

namespace BookManagementSystem.Model
{
   
    /// <summary>
    /// 用户实体类
    /// </summary>
    public class User
    {
   
        public int Id {
    get; set; }
        public string UserId {
    get; set; }
        public string Password {
    get; set; }
        public string UserName {
    get; set; }
        public UserType UserType {
    get; set; }
        public string Email {
    get; set; }
        public string Phone {
    get; set; }
        public DateTime RegisterDate {
    get; set; }
        public bool IsActive {
    get; set; }
    }

    public enum UserType
    {
   
        Admin = 1,     // 管理员
        Reader = 2     // 读者
    }
}

BorrowRecord.cs

namespace BookManagementSystem.Model
{
   
    /// <summary>
    /// 借阅记录实体类
    /// </summary>
    public class BorrowRecord
    {
   
        public int Id {
    get; set; }
        public int UserId {
    get; set; }
        public int BookId {
    get; set; }
        public DateTime BorrowDate {
    get; set; }
        public DateTime DueDate {
    get; set; }
        public DateTime? ReturnDate {
    get; set; }
        public BorrowStatus Status {
    get; set; }
        public decimal? FineAmount {
    get; set; }  // 罚款金额
    }

    public enum BorrowStatus
    {
   
        Borrowed = 1,      // 借出
        Returned = 2,      // 已归还
        Overdue = 3        // 逾期
    }
}

2.2 DAL层 - 数据访问层

IDbHelper.cs - 数据库辅助接口

using System.Data;

namespace BookManagementSystem.DAL
{
   
    public interface IDbHelper
    {
   
        IDbConnection CreateConnection();
        int ExecuteNonQuery(string sql, params IDbDataParameter[] parameters);
        object ExecuteScalar(string sql, params IDbDataParameter[] parameters);
        DataTable ExecuteDataTable(string sql, params IDbDataParameter[] parameters);
        IDataReader ExecuteReader(string sql, params IDbDataParameter[] parameters);
    }
}

SqlServerDbHelper.cs - SQL Server实现

using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace BookManagementSystem.DAL
{
   
    public class SqlServerDbHelper : IDbHelper
    {
   
        private readonly string _connectionString;

        public SqlServerDbHelper()
        {
   
            _connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
        }

        public IDbConnection CreateConnection()
        {
   
            return new SqlConnection(_connectionString);
        }

        public int ExecuteNonQuery(string sql, params IDbDataParameter[] parameters)
        {
   
            using (var conn = CreateConnection())
            {
   
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
   
                    cmd.CommandText = sql;
                    if (parameters != null)
                    {
   
                        foreach (var param in parameters)
                        {
   
                            cmd.Parameters.Add(param);
                        }
                    }
                    return cmd.ExecuteNonQuery();
                }
            }
        }

        public DataTable ExecuteDataTable(string sql, params IDbDataParameter[] parameters)
        {
   
            using (var conn = CreateConnection())
            {
   
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
   
                    cmd.CommandText = sql;
                    if (parameters != null)
                    {
   
                        foreach (var param in parameters)
                        {
   
                            cmd.Parameters.Add(param);
                        }
                    }
                    var dt = new DataTable();
                    using (var adapter = new SqlDataAdapter((SqlCommand)cmd))
                    {
   
                        adapter.Fill(dt);
                    }
                    return dt;
                }
            }
        }

        public object ExecuteScalar(string sql, params IDbDataParameter[] parameters)
        {
   
            using (var conn = CreateConnection())
            {
   
                conn.Open();
                using (var cmd = conn.CreateCommand())
                {
   
                    cmd.CommandText = sql;
                    if (parameters != null)
                    {
   
                        foreach (var param in parameters)
                        {
   
                            cmd.Parameters.Add(param);
                        }
                    }
                    return cmd.ExecuteScalar();
                }
            }
        }

        public IDataReader ExecuteReader(string sql, params IDbDataParameter[] parameters)
        {
   
            var conn = CreateConnection();
            conn.Open();
            var cmd = conn.CreateCommand();
            cmd.CommandText = sql;
            if (parameters != null)
            {
   
                foreach (var param in parameters)
                {
   
                    cmd.Parameters.Add(param);
                }
            }
            return cmd.ExecuteReader(CommandBehavior.CloseConnection);
        }
    }
}

IBookRepository.cs - 图书数据访问接口

using BookManagementSystem.Model;
using System.Collections.Generic;

namespace BookManagementSystem.DAL
{
   
    public interface IBookRepository
    {
   
        Book GetBookById(int id);
        List<Book> GetAllBooks();
        List<Book> SearchBooks(string keyword);
        int AddBook(Book book);
        bool UpdateBook(Book book);
        bool DeleteBook(int id);
        bool UpdateStock(int bookId, int quantity);
    }
}

BookRepository.cs - 图书数据访问实现

using BookManagementSystem.Model;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;

namespace BookManagementSystem.DAL
{
   
    public class BookRepository : IBookRepository
    {
   
        private readonly IDbHelper _dbHelper;

        public BookRepository(IDbHelper dbHelper)
        {
   
            _dbHelper = dbHelper;
        }

        public Book GetBookById(int id)
        {
   
            var sql = @"SELECT * FROM Books WHERE Id = @Id";
            var param = new SqlParameter("@Id", id);

            var dt = _dbHelper.ExecuteDataTable(sql, param);
            if (dt.Rows.Count > 0)
            {
   
                return MapToBook(dt.Rows[0]);
            }
            return null;
        }

        public List<Book> GetAllBooks()
        {
   
            var books = new List<Book>();
            var sql = @"SELECT * FROM Books ORDER BY CreateTime DESC";

            var dt = _dbHelper.ExecuteDataTable(sql);
            foreach (DataRow row in dt.Rows)
            {
   
                books.Add(MapToBook(row));
            }
            return books;
        }

        public List<Book> SearchBooks(string keyword)
        {
   
            var books = new List<Book>();
            var sql = @"SELECT * FROM Books 
                       WHERE Title LIKE @Keyword 
                          OR Author LIKE @Keyword 
                          OR ISBN LIKE @Keyword 
                          OR Publisher LIKE @Keyword";

            var param = new SqlParameter("@Keyword", $"%{keyword}%");
            var dt = _dbHelper.ExecuteDataTable(sql, param);

            foreach (DataRow row in dt.Rows)
            {
   
                books.Add(MapToBook(row));
            }
            return books;
        }

        public int AddBook(Book book)
        {
   
            var sql = @"INSERT INTO Books 
                       (ISBN, Title, Author, Publisher, PublishDate, 
                        Category, Price, Stock, AvailableStock, CreateTime, UpdateTime)
                       VALUES 
                       (@ISBN, @Title, @Author, @Publisher, @PublishDate,
                        @Category, @Price, @Stock, @AvailableStock, @CreateTime, @UpdateTime);
                       SELECT SCOPE_IDENTITY();";

            var parameters = new[]
            {
   
                new SqlParameter("@ISBN", book.ISBN),
                new SqlParameter("@Title", book.Title),
                new SqlParameter("@Author", book.Author),
                new SqlParameter("@Publisher", book.Publisher),
                new SqlParameter("@PublishDate", book.PublishDate),
                new SqlParameter("@Category", book.Category),
                new SqlParameter("@Price", book.Price),
                new SqlParameter("@Stock", book.Stock),
                new SqlParameter("@AvailableStock", book.AvailableStock),
                new SqlParameter("@CreateTime", DateTime.Now),
                new SqlParameter("@UpdateTime", DateTime.Now)
            };

            var result = _dbHelper.ExecuteScalar(sql, parameters);
            return Convert.ToInt32(result);
        }

        public bool UpdateBook(Book book)
        {
   
            var sql = @"UPDATE Books SET 
                       ISBN = @ISBN,
                       Title = @Title,
                       Author = @Author,
                       Publisher = @Publisher,
                       PublishDate = @PublishDate,
                       Category = @Category,
                       Price = @Price,
                       Stock = @Stock,
                       AvailableStock = @AvailableStock,
                       UpdateTime = @UpdateTime
                       WHERE Id = @Id";

            var parameters = new[]
            {
   
                new SqlParameter("@ISBN", book.ISBN),
                new SqlParameter("@Title", book.Title),
                new SqlParameter("@Author", book.Author),
                new SqlParameter("@Publisher", book.Publisher),
                new SqlParameter("@PublishDate", book.PublishDate),
                new SqlParameter("@Category", book.Category),
                new SqlParameter("@Price", book.Price),
                new SqlParameter("@Stock", book.Stock),
                new SqlParameter("@AvailableStock", book.AvailableStock),
                new SqlParameter("@UpdateTime", DateTime.Now),
                new SqlParameter("@Id", book.Id)
            };

            return _dbHelper.ExecuteNonQuery(sql, parameters) > 0;
        }

        public bool DeleteBook(int id)
        {
   
            var sql = "DELETE FROM Books WHERE Id = @Id";
            var param = new SqlParameter("@Id", id);

            return _dbHelper.ExecuteNonQuery(sql, param) > 0;
        }

        public bool UpdateStock(int bookId, int quantity)
        {
   
            var sql = @"UPDATE Books SET 
                       AvailableStock = AvailableStock + @Quantity,
                       UpdateTime = @UpdateTime
                       WHERE Id = @Id AND AvailableStock + @Quantity >= 0";

            var parameters = new[]
            {
   
                new SqlParameter("@Quantity", quantity),
                new SqlParameter("@UpdateTime", DateTime.Now),
                new SqlParameter("@Id", bookId)
            };

            return _dbHelper.ExecuteNonQuery(sql, parameters) > 0;
        }

        private Book MapToBook(DataRow row)
        {
   
            return new Book
            {
   
                Id = Convert.ToInt32(row["Id"]),
                ISBN = row["ISBN"].ToString(),
                Title = row["Title"].ToString(),
                Author = row["Author"].ToString(),
                Publisher = row["Publisher"].ToString(),
                PublishDate = Convert.ToDateTime(row["PublishDate"]),
                Category = row["Category"].ToString(),
                Price = Convert.ToDecimal(row["Price"]),
                Stock = Convert.ToInt32(row["Stock"]),
                AvailableStock = Convert.ToInt32(row["AvailableStock"]),
                CreateTime = Convert.ToDateTime(row["CreateTime"]),
                UpdateTime = Convert.ToDateTime(row["UpdateTime"])
            };
        }
    }
}

2.3 BLL层 - 业务逻辑层

IBookService.cs - 图书业务接口

using BookManagementSystem.Model;
using System.Collections.Generic;

namespace BookManagementSystem.BLL
{
   
    public interface IBookService
    {
   
        Book GetBookById(int id);
        List<Book> GetAllBooks();
        List<Book> SearchBooks(string keyword);
        OperationResult AddBook(Book book);
        OperationResult UpdateBook(Book book);
        OperationResult DeleteBook(int id);
        OperationResult BorrowBook(int userId, int bookId);
        OperationResult ReturnBook(int borrowRecordId);
        List<BorrowRecord> GetBorrowRecordsByUserId(int userId);
    }

    public class OperationResult
    {
   
        public bool Success {
    get; set; }
        public string Message {
    get; set; }
        public object Data {
    get; set; }

        public OperationResult(bool success, string message)
        {
   
            Success = success;
            Message = message;
        }

        public static OperationResult Ok(string message = "操作成功")
        {
   
            return new OperationResult(true, message);
        }

        public static OperationResult Fail(string message)
        {
   
            return new OperationResult(false, message);
        }
    }
}

BookService.cs - 图书业务实现

using BookManagementSystem.DAL;
using BookManagementSystem.Model;
using System;
using System.Collections.Generic;

namespace BookManagementSystem.BLL
{
   
    public class BookService : IBookService
    {
   
        private readonly IBookRepository _bookRepository;
        private readonly IBorrowRecordRepository _borrowRepository;
        private readonly IUserRepository _userRepository;

        public BookService(IBookRepository bookRepository, 
                          IBorrowRecordRepository borrowRepository,
                          IUserRepository userRepository)
        {
   
            _bookRepository = bookRepository;
            _borrowRepository = borrowRepository;
            _userRepository = userRepository;
        }

        public Book GetBookById(int id)
        {
   
            return _bookRepository.GetBookById(id);
        }

        public List<Book> GetAllBooks()
        {
   
            return _bookRepository.GetAllBooks();
        }

        public List<Book> SearchBooks(string keyword)
        {
   
            if (string.IsNullOrWhiteSpace(keyword))
            {
   
                return GetAllBooks();
            }
            return _bookRepository.SearchBooks(keyword);
        }

        public OperationResult AddBook(Book book)
        {
   
            try
            {
   
                // 验证数据
                if (string.IsNullOrWhiteSpace(book.ISBN))
                    return OperationResult.Fail("ISBN不能为空");

                if (string.IsNullOrWhiteSpace(book.Title))
                    return OperationResult.Fail("书名不能为空");

                if (book.Price < 0)
                    return OperationResult.Fail("价格不能为负数");

                if (book.Stock < 0)
                    return OperationResult.Fail("库存不能为负数");

                book.AvailableStock = book.Stock;

                int id = _bookRepository.AddBook(book);
                return OperationResult.Ok($"添加成功,图书ID:{id}");
            }
            catch (Exception ex)
            {
   
                return OperationResult.Fail($"添加失败:{ex.Message}");
            }
        }

        public OperationResult UpdateBook(Book book)
        {
   
            try
            {
   
                if (book == null)
                    return OperationResult.Fail("图书信息不能为空");

                var existingBook = _bookRepository.GetBookById(book.Id);
                if (existingBook == null)
                    return OperationResult.Fail("图书不存在");

                // 验证库存变化
                int stockDiff = book.Stock - existingBook.Stock;
                if (stockDiff != 0)
                {
   
                    book.AvailableStock = existingBook.AvailableStock + stockDiff;
                    if (book.AvailableStock < 0)
                        return OperationResult.Fail("可用库存不能为负数");
                }

                bool success = _bookRepository.UpdateBook(book);
                return success ? 
                    OperationResult.Ok("更新成功") : 
                    OperationResult.Fail("更新失败");
            }
            catch (Exception ex)
            {
   
                return OperationResult.Fail($"更新失败:{ex.Message}");
            }
        }

        public OperationResult DeleteBook(int id)
        {
   
            try
            {
   
                // 检查图书是否被借阅
                var borrowRecords = _borrowRepository.GetBorrowingRecordsByBookId(id);
                if (borrowRecords.Count > 0)
                    return OperationResult.Fail("该书有未归还记录,无法删除");

                bool success = _bookRepository.DeleteBook(id);
                return success ? 
                    OperationResult.Ok("删除成功") : 
                    OperationResult.Fail("删除失败");
            }
            catch (Exception ex)
            {
   
                return OperationResult.Fail($"删除失败:{ex.Message}");
            }
        }

        public OperationResult BorrowBook(int userId, int bookId)
        {
   
            try
            {
   
                // 检查用户是否存在
                var user = _userRepository.GetUserById(userId);
                if (user == null || !user.IsActive)
                    return OperationResult.Fail("用户不存在或已被禁用");

                // 检查图书是否存在且可借
                var book = _bookRepository.GetBookById(bookId);
                if (book == null)
                    return OperationResult.Fail("图书不存在");

                if (book.AvailableStock <= 0)
                    return OperationResult.Fail("图书库存不足");

                // 检查用户是否有逾期未还的图书
                var overdueRecords = _borrowRepository.GetOverdueRecordsByUserId(userId);
                if (overdueRecords.Count > 0)
                    return OperationResult.Fail("您有逾期未还的图书,请先归还");

                // 创建借阅记录
                var record = new BorrowRecord
                {
   
                    UserId = userId,
                    BookId = bookId,
                    BorrowDate = DateTime.Now,
                    DueDate = DateTime.Now.AddDays(30), // 借期30天
                    Status = BorrowStatus.Borrowed
                };

                int recordId = _borrowRepository.AddBorrowRecord(record);

                // 更新图书库存
                _bookRepository.UpdateStock(bookId, -1);

                return OperationResult.Ok($"借阅成功,借阅记录ID:{recordId}");
            }
            catch (Exception ex)
            {
   
                return OperationResult.Fail($"借阅失败:{ex.Message}");
            }
        }

        public OperationResult ReturnBook(int borrowRecordId)
        {
   
            try
            {
   
                var record = _borrowRepository.GetBorrowRecordById(borrowRecordId);
                if (record == null)
                    return OperationResult.Fail("借阅记录不存在");

                if (record.Status == BorrowStatus.Returned)
                    return OperationResult.Fail("图书已归还");

                // 更新归还信息
                record.ReturnDate = DateTime.Now;
                record.Status = BorrowStatus.Returned;

                // 计算是否逾期
                if (record.ReturnDate > record.DueDate)
                {
   
                    int overdueDays = (record.ReturnDate.Value - record.DueDate).Days;
                    record.FineAmount = overdueDays * 0.5m; // 每天0.5元罚款
                    record.Status = BorrowStatus.Overdue;
                }

                bool success = _borrowRepository.UpdateBorrowRecord(record);
                if (success)
                {
   
                    // 恢复图书库存
                    _bookRepository.UpdateStock(record.BookId, 1);
                    return OperationResult.Ok("归还成功");
                }

                return OperationResult.Fail("归还失败");
            }
            catch (Exception ex)
            {
   
                return OperationResult.Fail($"归还失败:{ex.Message}");
            }
        }

        public List<BorrowRecord> GetBorrowRecordsByUserId(int userId)
        {
   
            return _borrowRepository.GetBorrowRecordsByUserId(userId);
        }
    }
}

2.4 UI层 - WinForm界面

LoginForm.cs - 登录窗体

using BookManagementSystem.BLL;
using BookManagementSystem.Model;
using System;
using System.Windows.Forms;

namespace BookManagementSystem.UI
{
   
    public partial class LoginForm : Form
    {
   
        private readonly IUserService _userService;

        public LoginForm()
        {
   
            InitializeComponent();
            _userService = ServiceFactory.CreateUserService();
        }

        private void btnLogin_Click(object sender, EventArgs e)
        {
   
            string userId = txtUserId.Text.Trim();
            string password = txtPassword.Text;

            if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(password))
            {
   
                MessageBox.Show("请输入用户名和密码", "提示", 
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            var result = _userService.Login(userId, password);
            if (result.Success)
            {
   
                var user = result.Data as User;
                if (user != null)
                {
   
                    Session.CurrentUser = user;

                    // 根据用户类型打开不同界面
                    if (user.UserType == UserType.Admin)
                    {
   
                        var mainForm = new AdminMainForm();
                        mainForm.Show();
                    }
                    else
                    {
   
                        var mainForm = new ReaderMainForm();
                        mainForm.Show();
                    }

                    this.Hide();
                }
            }
            else
            {
   
                MessageBox.Show(result.Message, "登录失败", 
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnRegister_Click(object sender, EventArgs e)
        {
   
            var registerForm = new RegisterForm();
            registerForm.ShowDialog();
        }
    }
}

AdminMainForm.cs - 管理员主界面

using BookManagementSystem.BLL;
using BookManagementSystem.Model;
using System;
using System.Windows.Forms;

namespace BookManagementSystem.UI
{
   
    public partial class AdminMainForm : Form
    {
   
        private readonly IBookService _bookService;
        private readonly IUserService _userService;

        public AdminMainForm()
        {
   
            InitializeComponent();
            _bookService = ServiceFactory.CreateBookService();
            _userService = ServiceFactory.CreateUserService();

            LoadBooks();
            LoadUsers();
        }

        private void LoadBooks()
        {
   
            var books = _bookService.GetAllBooks();
            dgvBooks.DataSource = books;
        }

        private void LoadUsers()
        {
   
            var users = _userService.GetAllUsers();
            dgvUsers.DataSource = users;
        }

        private void btnAddBook_Click(object sender, EventArgs e)
        {
   
            var bookForm = new BookEditForm(null);
            if (bookForm.ShowDialog() == DialogResult.OK)
            {
   
                LoadBooks();
            }
        }

        private void btnEditBook_Click(object sender, EventArgs e)
        {
   
            if (dgvBooks.SelectedRows.Count > 0)
            {
   
                var book = dgvBooks.SelectedRows[0].DataBoundItem as Book;
                if (book != null)
                {
   
                    var bookForm = new BookEditForm(book);
                    if (bookForm.ShowDialog() == DialogResult.OK)
                    {
   
                        LoadBooks();
                    }
                }
            }
        }

        private void btnDeleteBook_Click(object sender, EventArgs e)
        {
   
            if (dgvBooks.SelectedRows.Count > 0)
            {
   
                var book = dgvBooks.SelectedRows[0].DataBoundItem as Book;
                if (book != null)
                {
   
                    if (MessageBox.Show($"确定要删除图书《{book.Title}》吗?", 
                        "确认删除", MessageBoxButtons.YesNo, 
                        MessageBoxIcon.Question) == DialogResult.Yes)
                    {
   
                        var result = _bookService.DeleteBook(book.Id);
                        MessageBox.Show(result.Message, 
                            result.Success ? "提示" : "错误",
                            MessageBoxButtons.OK, 
                            result.Success ? MessageBoxIcon.Information : MessageBoxIcon.Error);

                        if (result.Success)
                        {
   
                            LoadBooks();
                        }
                    }
                }
            }
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
   
            string keyword = txtSearch.Text.Trim();
            var books = _bookService.SearchBooks(keyword);
            dgvBooks.DataSource = books;
        }

        private void btnManageBorrow_Click(object sender, EventArgs e)
        {
   
            var borrowForm = new BorrowManageForm();
            borrowForm.ShowDialog();
        }

        private void btnUserManagement_Click(object sender, EventArgs e)
        {
   
            var userForm = new UserManagementForm();
            userForm.ShowDialog();
            LoadUsers();
        }

        private void btnStatistics_Click(object sender, EventArgs e)
        {
   
            var statisticsForm = new StatisticsForm();
            statisticsForm.ShowDialog();
        }
    }
}

3. 数据库脚本

SQL Server 数据库脚本

-- 创建数据库
CREATE DATABASE BookManagementDB;
GO

USE BookManagementDB;
GO

-- 用户表
CREATE TABLE Users (
    Id INT PRIMARY KEY IDENTITY(1,1),
    UserId VARCHAR(50) UNIQUE NOT NULL,
    Password VARCHAR(100) NOT NULL,
    UserName NVARCHAR(50) NOT NULL,
    UserType INT NOT NULL,  -- 1:管理员 2:读者
    Email VARCHAR(100),
    Phone VARCHAR(20),
    RegisterDate DATETIME NOT NULL DEFAULT GETDATE(),
    IsActive BIT NOT NULL DEFAULT 1,
    CONSTRAINT CK_UserType CHECK (UserType IN (1, 2))
);

-- 图书表
CREATE TABLE Books (
    Id INT PRIMARY KEY IDENTITY(1,1),
    ISBN VARCHAR(20) UNIQUE NOT NULL,
    Title NVARCHAR(200) NOT NULL,
    Author NVARCHAR(100) NOT NULL,
    Publisher NVARCHAR(100),
    PublishDate DATE,
    Category NVARCHAR(50),
    Price DECIMAL(10,2) NOT NULL DEFAULT 0,
    Stock INT NOT NULL DEFAULT 0,
    AvailableStock INT NOT NULL DEFAULT 0,
    CreateTime DATETIME NOT NULL DEFAULT GETDATE(),
    UpdateTime DATETIME NOT NULL DEFAULT GETDATE(),
    CONSTRAINT CK_Stock CHECK (Stock >= 0),
    CONSTRAINT CK_AvailableStock CHECK (AvailableStock >= 0 AND AvailableStock <= Stock)
);

-- 借阅记录表
CREATE TABLE BorrowRecords (
    Id INT PRIMARY KEY IDENTITY(1,1),
    UserId INT NOT NULL,
    BookId INT NOT NULL,
    BorrowDate DATETIME NOT NULL DEFAULT GETDATE(),
    DueDate DATETIME NOT NULL,
    ReturnDate DATETIME,
    Status INT NOT NULL DEFAULT 1,  -- 1:借出 2:已归还 3:逾期
    FineAmount DECIMAL(10,2) DEFAULT 0,
    FOREIGN KEY (UserId) REFERENCES Users(Id) ON DELETE CASCADE,
    FOREIGN KEY (BookId) REFERENCES Books(Id) ON DELETE NO ACTION,
    CONSTRAINT CK_Status CHECK (Status IN (1, 2, 3))
);

-- 创建索引
CREATE INDEX IX_Books_ISBN ON Books(ISBN);
CREATE INDEX IX_Books_Title ON Books(Title);
CREATE INDEX IX_Books_Author ON Books(Author);
CREATE INDEX IX_BorrowRecords_UserId ON BorrowRecords(UserId);
CREATE INDEX IX_BorrowRecords_BookId ON BorrowRecords(BookId);
CREATE INDEX IX_BorrowRecords_Status ON BorrowRecords(Status);

-- 插入测试数据
-- 插入管理员用户
INSERT INTO Users (UserId, Password, UserName, UserType, Email, IsActive)
VALUES ('admin', '123456', '系统管理员', 1, 'admin@library.com', 1);

-- 插入普通读者
INSERT INTO Users (UserId, Password, UserName, UserType, Email, IsActive)
VALUES ('reader001', '123456', '张三', 2, 'zhangsan@example.com', 1);

-- 插入测试图书
INSERT INTO Books (ISBN, Title, Author, Publisher, PublishDate, Category, Price, Stock, AvailableStock)
VALUES 
('9787111126768', 'C#入门经典', 'John Sharp', '清华大学出版社', '2020-01-01', '计算机', 89.00, 10, 10),
('9787302455106', 'ASP.NET Core实战', 'Andrew Lock', '电子工业出版社', '2021-03-15', '计算机', 99.00, 5, 5),
('9787302518368', '数据库系统概念', 'Abraham Silberschatz', '机械工业出版社', '2019-05-20', '计算机', 128.00, 8, 8),
('9787544285147', '解忧杂货店', '东野圭吾', '南海出版公司', '2014-05-01', '文学', 39.50, 15, 15);

4. 配置文件

App.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <connectionStrings>
        <add name="DefaultConnection" 
             connectionString="Data Source=.;Initial Catalog=BookManagementDB;Integrated Security=True;TrustServerCertificate=True" 
             providerName="System.Data.SqlClient"/>
    </connectionStrings>

    <appSettings>
        <add key="BorrowDays" value="30"/>
        <add key="FinePerDay" value="0.5"/>
        <add key="MaxBorrowCount" value="5"/>
    </appSettings>

    <system.diagnostics>
        <sources>
            <source name="BookManagementSystem" switchValue="Information">
                <listeners>
                    <add name="fileLog"/>
                </listeners>
            </source>
        </sources>
        <sharedListeners>
            <add name="fileLog"
                 type="System.Diagnostics.TextWriterTraceListener"
                 initializeData="logs\BookManagement.log"/>
        </sharedListeners>
    </system.diagnostics>
</configuration>

5. 项目依赖项

在项目中需要安装以下NuGet包:

<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />

参考代码 C# 图书管理系统(三层架构) www.youwenfan.com/contentalg/93652.html

6. 设计要点

三层架构的优势:

  1. 分离关注点:各层职责明确,便于维护
  2. 可扩展性:可以轻松替换数据访问技术(如切换数据库)
  3. 可测试性:便于编写单元测试
  4. 复用性:业务逻辑可以在不同表示层中复用

关键特性实现:

  1. 图书管理:CRUD操作、库存管理
  2. 用户管理:角色权限控制(管理员/读者)
  3. 借阅管理:借书、还书、逾期处理
  4. 搜索功能:多条件图书搜索
  5. 数据验证:业务规则验证
  6. 异常处理:统一的错误处理机制

这个系统可以扩展以下功能:

  1. 图书分类管理
  2. 读者评级系统
  3. 预约功能
  4. 电子书管理
  5. 报表统计
  6. 数据导入导出
  7. 邮件通知系统
相关文章
|
2月前
|
人工智能 前端开发 算法
大厂CIO独家分享:AI如何重塑开发者未来十年
在 AI 时代,若你还在紧盯代码量、执着于全栈工程师的招聘,或者仅凭技术贡献率来评判价值,执着于业务提效的比例而忽略产研价值,你很可能已经被所谓的“常识”困住了脚步。
1501 89
大厂CIO独家分享:AI如何重塑开发者未来十年
|
2月前
|
缓存 网络协议 安全
基于C#实现欧姆龙PLC FINS/TCP通信
基于C#实现欧姆龙PLC FINS/TCP通信
|
1月前
|
监控 Kubernetes 调度
干货推荐:容器可观测新视角—SysOM 延时抖动监控助力定位业务抖动原因
为了解决这一挑战,本文将结合实战案例,介绍如何在 Kubernetes 环境中使用 ack-sysom-monitor Exporter 对内核延迟进行可视化分析与定位,帮助你快速识别问题根因,并高效缓解由延迟引发的业务抖动。
|
12天前
|
SQL BI 网络安全
SQL Server 2008 SP2 补丁包安装步骤(x64中文版)
本文介绍在Windows x64系统上为SQL Server 2008原版安装SP2补丁的完整步骤。需先关闭杀软和防火墙,以管理员身份运行安装包,解压后通过安装向导依次完成环境检测、实例选择、组件更新与安装。安装后可通过sqlcmd或SSMS验证版本号是否变为10.0.4000,确认补丁生效。全过程需确保权限与版本匹配。
|
24天前
|
传感器 安全 前端开发
电路安全防线,平芯微过压过流保护芯片深度解析与应用指南
电路安全防线,平芯微过压过流保护芯片深度解析与应用指南
|
1月前
|
JSON 监控 数据可视化
云监控 UModel Explorer:用“图形化”重新定义可观测数据建模
阿里云 UModel Explorer 正式发布:告别复杂配置,拖拽即建模,点击即洞察,实现建模、探索、分析一体化,让可观测真正高效协同,开启可视化运维新时代!
342 51
|
27天前
|
人工智能 自然语言处理 算法
GEO优化不踩坑:不同规模企业的服务商选择与落地干货
AI搜索崛起,GEO成流量新风口。企业需根据规模与行业精准选择服务商:大企业重全球布局与合规,选即搜AI、Moz;中小微求性价比与速效,边鱼科技、Ahrefs更适配。结合实操案例与签约避坑指南,助力品牌高效抢占AI推荐红利,实现线索与订单双增长。(238字)
|
28天前
|
消息中间件 人工智能 NoSQL
AgentScope x RocketMQ:打造企业级高可靠 A2A 智能体通信基座
基于 RocketMQ SDK 实现了 A2A 协议的 ClientTransport 接口(部分核心代码现已开源),并与 AgentScope 框架深度集成,共同构建了全新的 A2A 智能体通信基座,为多智能体应用提供企业级、高可靠的异步协同方案。
325 48
|
1月前
|
运维 监控 前端开发
基于AI大模型的故障诊断与根因分析落地实现
本项目基于Dify平台构建多智能体协作的AIOps故障诊断系统,融合指标、日志、链路等多源数据,通过ReAct模式实现自动化根因分析(RCA),结合MCP工具调用与分层工作流,在钉钉/企业微信中以交互式报告辅助运维,显著降低MTTD/MTTR。
1608 28