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

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

使用EFCore处理并发冲突的更多相关文章

  1. Linq to Sql : 并发冲突及处理策略

    原文:Linq to Sql : 并发冲突及处理策略 1. 通过覆盖数据库值解决并发冲突 try { db.SubmitChanges(ConflictMode.ContinueOnConflict) ...

  2. LINQ-to-SQL那点事~LINQ-to-SQL中的并发冲突与应对

    回到目录 在上一篇文章中提到了并发冲突,还说详细的说明在这讲来说,呵呵,那现在就说一下吧! 并发冲突产生的原因 事实上,linq to sql中的并发冲突是指记录在进行update操作时,客户端A1取 ...

  3. Mego开发文档 - 处理并发冲突

    处理并发冲突 数据库并发是指多个进程或用户同时访问或更改数据库中的相同数据的情况.并发控制是指用于确保存在并发更改时数据一致性的特定机制. Mego实现了乐观并发控制,这意味着它可以让多个进程或用户独 ...

  4. asp.net core 系列之并发冲突

    本文介绍如何处理多个用户并发更新同一实体(同时)时出现的冲突 . 主要是两种:一种,检查属性并发冲突,使用 [ConcurrencyCheck] ;另一种,检测行的并发冲突,使用 rowversion ...

  5. MySQL事物(一)事务隔离级别和事物并发冲突

    数据库的操作通常为写和读,就是所说的CRUD:增加(Create).读取(Read).更新(Update)和删除(Delete).事务就是一件完整要做的事情.事务是恢复和并发控制的基本单位.事务必须始 ...

  6. Linq to Sql并发冲突及处理策略

    0. 并发冲突的示例 单用户的系统现在应该比较罕见了,一般系统都会有很多用户在同时进行操作:在多用户系统中,涉及到的一个普遍问题:当多个用户“同时”更新(修改或者删除)同一条记录时,该如何更新呢?   ...

  7. C# 开放式并发冲突报错处理

    1.调用DataSet.GetChanges()获取数据源中改变的数据 var data = ViewData.GetChanges() as ReleaseData; 2.为新增的数据 data 加 ...

  8. Elasticsearch由浅入深(四)ES并发冲突、悲观锁与乐观锁、_version乐观锁并发

    ES并发冲突 举个例子,比如是电商场景下,假设说,我们有个程序,工作的流程是这样子的: 读取商品信息(包含了商品库存) 用户下单购买 更新商品信息(主要是将库存减1) 我们比如咱们的程序就是多线程的, ...

  9. 分布式缓存重建并发冲突和zookeeper分布式锁解决方案

    如果缓存服务在本地的ehcache中都读取不到数据. 这个时候就意味着,需要重新到源头的服务中去拉去数据,拉取到数据之后,赶紧先给nginx的请求返回,同时将数据写入ehcache和redis中 分布 ...

随机推荐

  1. 哆啦A梦css

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. layer结合art实现弹出功能

    模板 <!-- 模板 --> <script id="render-tpl" type="text/html"> <table c ...

  3. MPU6050可以读取器件ID值,但读出的加速度计和陀螺仪的数据均为零

    今天在调试MPU6050时发现,MPU6050可以正常读取器件ID,但读取的加速度计和陀螺仪的数据均为零. 经过排查发现,MPU6050第20脚的电容没用焊接,C6可以使用10uF的电容.

  4. js斐波那契数列

    斐波那契数列指的是这样一个数列 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89...... 这个数列从第3项开始,每一项都等于前两项之和. 1.递归算法: function ...

  5. java异常处理try catch finally

    1       异常 1.1      异常处理的作用 在编程时,如果出现文件打开失败,读写文件就会异常退出.如果出现内存溢出错误,程序也会异常退出.如果不能对这些异常进行处理.程序则无法正常运行.所 ...

  6. python常用技巧

    1,关于tab键与4个空格: 由于不同平台间,tab键值设置有所区别,据相关介绍,官方在缩进方面推荐使用4个空格.方便起见,可设置tab自动转换为4个空格. 1.1在pycharm中:    通过fi ...

  7. git pull和本地文件冲突

    在使用git pull代码时,经常会碰到有冲突的情况,提示如下信息: error: Your local changes to 'c/environ.c' would be overwritten b ...

  8. urllib库详解 --Python3

    相关:urllib是python内置的http请求库,本文介绍urllib三个模块:请求模块urllib.request.异常处理模块urllib.error.url解析模块urllib.parse. ...

  9. vue使用webapck的最基本最简单的开发环境配置

    这个配置生成出来的代码只能支持ES6的浏览器下正常显示. npm init -y npm install vue-loader vue-template-compiler vue-style-load ...

  10. scrapyd的安装和scrapyd-client

    1.创建虚拟环境  ,虚拟环境名为sd mkvirtualenv sd #方便管理 2. 安装 scrapyd pip3 install scrapyd 3. 配置 mkdir /etc/scrapy ...