MVC中如何实现数据库图书库存递减及租书限制功能?
图书租借功能修复与实现方案
问题根源
- 仓储Update方法无效:当前
Update仅调用SaveChanges(),但传入的book是脱离EF上下文的实例,EF无法识别属性变更,导致数据库无更新。 - 缺失库存校验:未在租借前检查图书库存是否为0,无法拦截无效租借请求。
- 并发风险:直接使用前端传入的库存值,多用户同时操作时会导致库存计算错误。
修复与实现代码
1. 修复通用仓储的Update方法
修改GenericRepository<T>的Update逻辑,让EF能跟踪实体变更:
public class GenericRepository<T> where T:class,new() { LibraryEntities db = new LibraryEntities(); // 其他方法保持不变... public void Update(T par) { var entry = db.Entry(par); // 若实体未被上下文跟踪,先附加并标记为修改状态 if (entry.State == EntityState.Detached) { db.Set<T>().Attach(par); entry.State = EntityState.Modified; } db.SaveChanges(); } }
2. 完善RentBook控制器方法
添加库存校验、获取最新图书数据,避免并发问题:
[HttpPost] public ActionResult RentBook(int bookId) { User data = TempData["userdata"] as User; if (data == null) { ViewBag.ErrorMessage = "请先登录!"; return RedirectToAction("index", "login"); } // 从数据库拉取最新图书数据,确保库存是实时状态 var targetBook = bookrepo.TGet(bookId); if (targetBook == null) { ViewBag.ErrorMessage = "该图书不存在!"; return RedirectToAction("index", "Home"); } // 库存为0时拦截租借 if (targetBook.NumberofBooks <= 0) { ViewBag.ErrorMessage = "You can't rent this book"; return RedirectToAction("index", "Home"); } // 递减库存并更新 targetBook.NumberofBooks -= 1; bookrepo.Update(targetBook); // 创建租借记录 var rentedRecord = new Table_RentedBooks { RecordDate = DateTime.Now, DeliveryDate = DateTime.Now.AddDays(14), UserID = data.UserID, BookID = bookId }; rentedrepo.Add(rentedRecord); return RedirectToAction("index", "Home"); }
3. 前端提示展示(可选)
在Home/Index视图中添加提示渲染逻辑:
@if (!string.IsNullOrEmpty(ViewBag.ErrorMessage)) { <div class="alert alert-danger">@ViewBag.ErrorMessage</div> }
核心注意点
- 优先使用数据库最新数据:通过
bookId从数据库重新获取图书,避免前端数据篡改和并发冲突。 - EF实体状态管理:确保修改的实体处于上下文跟踪状态,EF才能生成正确的更新SQL。
- 库存校验时机:必须在获取实时库存后立即校验,防止多用户同时操作导致库存负数。
内容的提问来源于stack exchange,提问作者user17847724
相关产品推荐
相关产品推荐

