You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core中点击按钮修改书籍Availability属性的实现异常问题

问题分析与解决

你的代码存在两个关键问题,直接导致了空引用异常和库存更新不生效:

  • 未持久化数据库修改:修改书籍Availability属性后,没有调用EF Core的保存方法,更新不会写入数据库。
  • 视图无有效模型传入:直接返回View("Index")但未传递书籍列表数据,Razor视图接收的Model为null,遍历触发NullReferenceException。

修复方案

1. 修正Loan方法,完成更新保存与模型传递

修改后的方法需同时实现库存修改、数据库保存、更新后数据查询三个核心动作:

public async Task<IActionResult> Loan(string id)
{
    if (id == null || _context.Books == null)
    {
        return NotFound();
    }

    var book = await _context.Books
        .FirstOrDefaultAsync(m => m.BookCode == id);
    if (book == null)
    {
        return NotFound();
    }
    else if (book.Availability == 0)
    { 
        return BadRequest(new { Message = "书籍已无库存,无法借出" });
    }
    else 
    {
        // 减少库存
        book.Availability = (sbyte)(book.Availability - 1);
        // 将更新写入数据库
        await _context.SaveChangesAsync();
        // 查询更新后的完整书籍列表
        var updatedBooks = await _context.Books.ToListAsync();
        // 传递模型到Index视图
        return View("Index", updatedBooks);
    }
}

2. 实现归还功能(复用借出逻辑)

按照相同逻辑编写归还方法,完成库存加1操作:

public async Task<IActionResult> Return(string id)
{
    if (id == null || _context.Books == null)
    {
        return NotFound();
    }

    var book = await _context.Books
        .FirstOrDefaultAsync(m => m.BookCode == id);
    if (book == null)
    {
        return NotFound();
    }
    else
    {
        // 增加库存
        book.Availability = (sbyte)(book.Availability + 1);
        // 保存到数据库
        await _context.SaveChangesAsync();
        // 查询更新后的书籍列表
        var updatedBooks = await _context.Books.ToListAsync();
        // 返回视图并传递模型
        return View("Index", updatedBooks);
    }
}

3. 视图增加空值保护(可选但推荐)

在视图遍历前添加空值判断,避免后续类似异常:

@if (Model == null || !Model.Any())
{
    <tr>
        <td colspan="5">暂无书籍数据</td>
    </tr>
}
else
{
    @foreach (var item in Model) 
    {
        <tr>
            <td>@Html.DisplayFor(modelItem => item.Title)</td>
            <td>@Html.DisplayFor(modelItem => item.Author)</td>
            <td>@Html.DisplayFor(modelItem => item.YearPublished)</td>
            <td>@Html.DisplayFor(modelItem => item.BookCode)</td>
            <td>@Html.DisplayFor(modelItem => item.Availability)</td>
            <td>
                @if (item.Availability > 0)
                {
                    <a asp-action="Loan" asp-route-id="@item.BookCode">借出</a>
                }
                <a asp-action="Return" asp-route-id="@item.BookCode">归还</a>
            </td>
        </tr>
    }
}

优化建议(PRG模式)

如果你的Index方法已经实现了书籍列表查询逻辑,建议修改为重定向到Index方法,符合Post/Redirect/Get模式,避免重复提交问题:

// 替换Loan方法中返回视图的代码
return RedirectToAction(nameof(Index));

对应的Index方法需保证能正确传递模型:

public async Task<IActionResult> Index()
{
    return _context.Books != null ? 
                View(await _context.Books.ToListAsync()) :
                Problem("Entity set 'YourDbContext.Books' is null.");
}

内容的提问来源于stack exchange,提问作者insolentmamba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:56:06