使用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>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM