一、首先添加并发处理标记
在需要进行并发处理的类中添加版本号,并在版本号上使用[Timestamp]标记:
public class Department { public int Id { get; set;}
public …… public int? InstructorId{ get; set; } public ICollection<Course> Courses {get; set; }
//版本号 [Timestamp] public byte[] RowVersion{get; set; } }
二、然后更新数据库
add-migration updateTimestampForDeparment
update-database
三、重新建基架项目
删除Create和Edit页面内关于RowVersion项目的输入项
四、打开编辑Edit的控制器,修改如下:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Edit(int? id, byte[]rowVersion) { if(id==null) { return NoFound(); } //先查一下数据是否存在 var department= await _context.Departments.Include(a=>a.Administrator) .SingleOrDefaultAsync(a=>a.Id==id); if(department==null) { var deletedDepartment = new Department(); await TryUpdateModeAsync(deletedDepartment); ModelState.AddModelError(string.Empty,"无法进行数据的修改,该部门信息已经被其他人删除!); ViewBag.InstructorId = new SelectList(_context.Instructors, "Id","RealName",deletedDepartment); return View(deletedDepartment); } //将RowVersion标志原来的值变更为新的值 _context.Entry(department).Property("RowVersion").OriginalValue = rowVersion; if(await TryUpdateModelAsync<Department>(department, a=>a.Name, a=>a.StartDate, a=>a.Budge(a=>a.InstructorId)) { try { await _context.SaveChangesAsync();
return RedireToAction(nameof(Index));
}
catch(DbUpdateException ex)
{
var exceptionEntity = ex.Entries.Single();
var clienValue = (Department)exceptionEntity.Entity;
var databaseEntity = exceptionEntity.GetDatabaseValues();
if(databaseEntity == null)
{
ModelState.AddModelError(string.Empty, "无法进行数据的修改,该部门信息已经被其他人删除!);
}
else{
var databaseValues=(Dapartment)databaseEntity.ToObject();
if(databaseValues.Budget != clienValue.Budget)
{
ModelState.AddModelErrow("Budget", $"当前值:{databaseValues.Budget}");
}
if(databaseValues.StartDate != clienValue.StartDate)
{
ModelState.AddModelErrow("StartDate", $"当前值:{databaseValues.StartDate}");
}
if(databaseValues.InstructorId != clienValue.InstructorId)
{
var instructorEntity = await _context.Instructors.SingleOrDfaultAsync(a=>a.Id == databaseValues.InstructorId);
ModelState.AddModelErrow("InstructorId", $"当前值:{instructorEntity?.RealName}");
}
ModelState.AddModelErrow("", "你正在编辑的记录已经被其他用户所修改,编辑操作已经被取消,数据库当前的值已经显示在页面,请再次点击保存。否则请返回列表");
department.RowVersion=(byte[])databaseValues.RowVersion;
ModelState.Remove("RowVersion");
}
}
}
ViewBag.InstructorId=new SelectList(_context.Instructors, "Id","RealName",deletedDepartment)
return View(department);
}
五、修改Edit视图
添加版本号字段到Form中
<input type="hidden" asp-for="RowVersion" />
六、修改删除控制器
public async Task<IActionResult> Delete(int? id, bool? concurrencyError) { if( id == null) { return NotFound(); } var department = await _context.Departments .include(d=>d.Administrator).AsNoTracking() .singleOrDefaultAsync(m=>m.Id==id); if(department == null) { if(concurrencyError.GetValueOrDefault()); { return RedirectToAction(nameof(Index)); } return NotFound(); } if(concurrencyError.GetValueOrDefault()); { ViewBag.concurrencyErrow = "你正在删除的信息,已经被别人修改了,当前操作会被取消,如果你要继续删除该条信息,请重新点击删除按钮,否则请返回列表"; } return View(department); }
七、修改删除确认控制器
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> DeleteConfirmed(Department department) { try { if(await _context.Departments.AnyAsync(a=>a.Id==department.id) { _context.Departments.Remove(department); await _context.SaveChangesAsync(); } return RedirectToAction(nameof(Index)); } catch(DbUpdateException e) { return RedirectToAction(nameof(Delete),new {concurrencyError = true, id = department.Id}); } }
八、修改删除视图
在视图中添加报错信息的显示块:
<p class="text-denger">@Viewbag.</p>