• 使用EFCore处理并发冲突


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

    在需要进行并发处理的类中添加版本号,并在版本号上使用[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>
  • 相关阅读:
    WebStorm 使用
    Mac上因磁盘格式导致gulp无限刷新问题
    JS数组随机排序
    Javascript高性能动画与页面渲染
    两列布局,左边固定,右边自适应的三种方法
    google pay app权限使用说明
    javaFX
    https网站引用http路径的js和css失效解决办法
    tomcat笔记
    java sigar.jar
  • 原文地址:https://www.cnblogs.com/sky-net/p/9242775.html
Copyright © 2020-2023  润新知