一、首先添加並發處理標記
在需要進行並發處理的類中添加版本號,並在版本號上使用[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>
