使用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>
使用EFCore处理并发冲突的更多相关文章
- Linq to Sql : 并发冲突及处理策略
原文:Linq to Sql : 并发冲突及处理策略 1. 通过覆盖数据库值解决并发冲突 try { db.SubmitChanges(ConflictMode.ContinueOnConflict) ...
- LINQ-to-SQL那点事~LINQ-to-SQL中的并发冲突与应对
回到目录 在上一篇文章中提到了并发冲突,还说详细的说明在这讲来说,呵呵,那现在就说一下吧! 并发冲突产生的原因 事实上,linq to sql中的并发冲突是指记录在进行update操作时,客户端A1取 ...
- Mego开发文档 - 处理并发冲突
处理并发冲突 数据库并发是指多个进程或用户同时访问或更改数据库中的相同数据的情况.并发控制是指用于确保存在并发更改时数据一致性的特定机制. Mego实现了乐观并发控制,这意味着它可以让多个进程或用户独 ...
- asp.net core 系列之并发冲突
本文介绍如何处理多个用户并发更新同一实体(同时)时出现的冲突 . 主要是两种:一种,检查属性并发冲突,使用 [ConcurrencyCheck] ;另一种,检测行的并发冲突,使用 rowversion ...
- MySQL事物(一)事务隔离级别和事物并发冲突
数据库的操作通常为写和读,就是所说的CRUD:增加(Create).读取(Read).更新(Update)和删除(Delete).事务就是一件完整要做的事情.事务是恢复和并发控制的基本单位.事务必须始 ...
- Linq to Sql并发冲突及处理策略
0. 并发冲突的示例 单用户的系统现在应该比较罕见了,一般系统都会有很多用户在同时进行操作:在多用户系统中,涉及到的一个普遍问题:当多个用户“同时”更新(修改或者删除)同一条记录时,该如何更新呢? ...
- C# 开放式并发冲突报错处理
1.调用DataSet.GetChanges()获取数据源中改变的数据 var data = ViewData.GetChanges() as ReleaseData; 2.为新增的数据 data 加 ...
- Elasticsearch由浅入深(四)ES并发冲突、悲观锁与乐观锁、_version乐观锁并发
ES并发冲突 举个例子,比如是电商场景下,假设说,我们有个程序,工作的流程是这样子的: 读取商品信息(包含了商品库存) 用户下单购买 更新商品信息(主要是将库存减1) 我们比如咱们的程序就是多线程的, ...
- 分布式缓存重建并发冲突和zookeeper分布式锁解决方案
如果缓存服务在本地的ehcache中都读取不到数据. 这个时候就意味着,需要重新到源头的服务中去拉去数据,拉取到数据之后,赶紧先给nginx的请求返回,同时将数据写入ehcache和redis中 分布 ...
随机推荐
- python打包分发工具setuptools使用记录
关于python setup.py文件的编写技巧 环境:最新版setuptools,初步认识setuptools可以参考这篇文章 1. 自定义命令 from setuptools import set ...
- HBase RegionServer Splitting 流程
RegionServer Splitting 实现 HBase 中的写请求由 Region Server 处理,这些数据首先存储在 memstore (RegionServer 里的一个存储系统)里. ...
- WebvirtCloud安装(CentOS7)
1.安装依赖包wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repoyum -y install p ...
- java.nio.file.NoSuchFileException
springboot +es es 2.1.0 参考这个 https://www.cnblogs.com/yueshutong/p/9381543.html cluster-nodes :改成127. ...
- xlwt模块的使用
前记:Python处理表格时会用到xlwt和xlrd模块 xlwt设置行高:row sheet.row(2).set_style(xlwt.easyxf('font:height 440;')) 13 ...
- spring boot2.0(二 ) lettcute访问redis
前言 此处已经省略redis的安装,请自行百度查找redis的服务端安装过程. 1.pom文件配置: <project xmlns="http://maven.apache.org/P ...
- bilinear pooling
一.双线性汇合的计算过程: 第一步,计算Gram 矩阵: 对于一组H×W×D的feature maps,$\boldsymbol{x}_{i} \in \mathbb{R}^{D}$是图像的深度描述, ...
- scatter参数
列出scatter常用的一些参数: plt.scatter(x,y,c= '颜色可选',marker= '点的样式', cmap= '颜色变化',alpha=“透明度”, linewidths=“线宽 ...
- learning websocket protocol
websocket的产生背景: 众所周知,Web应用的通信过程通常是客户端通过浏览器发出一个请求,服务器端接收请求后进行处理并返回结果给客户端,客户端浏览器将信息呈现.这种机制对于信息变化不是特别频繁 ...
- learning makefile call func