使用EFCore處理併發衝突

1、首先添加併發處理標記數據庫

在須要進行併發處理的類中添加版本號,並在版本號上使用[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; } }

2、而後更新數據庫async

add-migration updateTimestampForDeparmentspa

update-databasecode

3、從新建基架項目orm

刪除Create和Edit頁面內關於RowVersion項目的輸入項blog

4、打開編輯Edit的控制器,修改以下:get

[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);
}

 5、修改Edit視圖input

添加版本號字段到Form中string

<input type="hidden" asp-for="RowVersion" />

 

6、修改刪除控制器

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);
}

7、修改刪除確認控制器

[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});
     }
}

 8、修改刪除視圖

在視圖中添加報錯信息的顯示塊:

<p class="text-denger">@Viewbag.</p>
相關文章
相關標籤/搜索