一、首先添加并发处理标记

在需要进行并发处理的类中添加版本号,并在版本号上使用[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>