学习 ASP.NET Core Razor 编程系列目录
学习 ASP.NET Core Razor 编程系列一
学习 ASP.NET Core Razor 编程系列二 -- 添加一个实体
学习 ASP.NET Core Razor 编程系列三 -- 创建数据表及创建项目基本页面
学习 ASP.NET Core Razor 编程系列四 --Asp.Net Core Razor 列表模板页面
学习 ASP.NET Core Razor 编程系列五 --Asp.Net Core Razor 新建模板页面
学习 ASP.NET Core Razor 编程系列六 -- 数据库初始化
学习 ASP.NET Core Razor 编程系列七 -- 修改列表页面
并发异常处理
在 Visual Studio 2017 的解决方案资源管理器中找到 Pages/Books/Edit.cshtml.cs 文件, 鼠标双击打开 , 在代码中找到 OnPostAsync 方法. 并按如下代码进行修改:
- public async Task<IActionResult> OnPostAsync()
- {
- if (!ModelState.IsValid)
- {
- return Page();
- }
- _context.Attach(Book).State = EntityState.Modified;
- try
- {
- await _context.SaveChangesAsync();
- }
- catch (DbUpdateConcurrencyException)
- {
- if (!_context.Book.Any(e => e.ID == Book.ID))
- {
- return NotFound();
- }
- else
- {
- throw;
- }
- }
- return RedirectToPage("./Index");
- }
上面的代码功能是当检测到第一个客户端在删除书籍信息时, 第二个客户端对要删除的书籍信息进行修改并保存时发生异常.
我们可以进行以下操作来重现上面的异常.
在 catch (DbUpdateConcurrencyException) 上设置断点. 如下图.
2. 在 Visual Studio 2017 中按 F5, 运行应用程序, 在打开的浏览器的一个窗口中, 选择一本书籍进行修改. 如下图.
3. 在另一个浏览器窗口中, 选择同一本书籍信息的 "Delete" 链接, 然后删除此书籍.
4. 在编辑书籍信息的浏览器窗口中, 将书籍信息的修改内容保存到数据库. 如下图.
5. 当两个或更多客户端同时更新记录时, 代码通常将检测到并发冲突. 如下图.
GET 请求与 POST 请求
接下来我们根据 Pages/Books/Edit.cshtml.cs 文件内容来介绍一下请求过程, 代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.AspNetCore.Mvc.RazorPages;
- using Microsoft.AspNetCore.Mvc.Rendering;
- using Microsoft.EntityFrameworkCore;
- using RazorMvcBooks.Models;
- namespace RazorMvcBooks.Pages.Books
- {
- public class EditModel : PageModel
- {
- private readonly RazorMvcBooks.Models.BookContext _context;
- public EditModel(RazorMvcBooks.Models.BookContext context)
- {
- _context = context;
- }
- [BindProperty]
- public Book Book { get; set; }
- public async Task<IActionResult> OnGetAsync(int? id)
- {
- if (id == null)
- {
- return NotFound();
- }
- Book = await _context.Book.SingleOrDefaultAsync(m => m.ID == id);
- if (Book == null)
- {
- return NotFound();
- }
- return Page();
- }
- public async Task<IActionResult> OnPostAsync()
- {
- if (!ModelState.IsValid)
- {
- return Page();
- }
- _context.Attach(Book).State = EntityState.Modified;
- try
- {
- await _context.SaveChangesAsync();
- }
- catch (DbUpdateConcurrencyException)
- {
- if (!_context.Book.Any(e => e.ID == Book.ID))
- {
- return NotFound();
- }
- else
- {
- throw;
- }
- }
- return RedirectToPage("./Index");
- }
- }
- }
1. 当浏览器对 Books/Edit 页面发出 HTTP GET 请求时 (例如 http://localhost:5000/Books/Edit/9 ):
OnGetAsync 方法从数据库提取书籍信息并把数据传递给 Page 方法.
Page 方法呈现 "Pages/Books/Edit.cshtml"Razor 页面. Pages/Books/Edit.cshtml 文件包含实体指令 (@model RazorMvcBooks.Pages.Books.EditModel), 这使书籍实体在页面上可用.
页面中的表单会显示书籍实体中的值.
2. 当浏览器对 Books/Edit 页面发出 Post 请求时:
此页面上的表单值将绑定到 Book 属性上. [BindProperty] 特性会启用实体属性绑定. 具体代码参见上面的代码.
如果实体对象的属性值中存在错误 (例如, ReleaseDate 无法被转换为日期), 则会使用已提交的值再次请求表单.
如果实体对象的属性值中没有错误, 则把书籍信息保存到数据库.
"Index.cshtml","Create.cshtml" 和 "delete.cshtml"Razor 页面中的 HTTP GET 方法的实现原理与上面所述的 Get 请求类似. "Create.cshtml"Razor 页面中的 POST 请求方法的实现原理与上面所述的 POST 请求类似.
来源: https://www.cnblogs.com/chillsrc/p/8986512.html