使用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中 分布 ...
随机推荐
- 51nod 1201 整数划分 dp
1201 整数划分 基准时间限制:1 秒 空间限制:131072 KB 收藏 关注 将N分为若干个不同整数的和,有多少种不同的划分方式,例如:n = 6,{6} {1,5} {2,4} {1,2 ...
- Xiangqi(简单模拟)
4746: Xiangqi 时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte 总提交: 15 测试通过:2 描述 Xiangqi i ...
- Hibernate实例——Customer表的展示
Hibernate.cfg.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibe ...
- lua 5.3.5 安装/初体验
安装 官网http://www.lua.org/start.html 参考 https://blog.csdn.net/qq_23954569/article/details/70879672 cd ...
- (详细)华为V9 DUK-AL20的usb调试模式在哪里打开的方法
当我们使用PC通过数据线链接到安卓手机的时候,如果手机没有开启USB开发者调试模式,PC则没办法成功识别我们的手机,有时我们使用的一些功能较好的软件好比以前我们使用的一个软件引号精灵,老版本就需要打开 ...
- 另类AOP设计
常见的AOP设计都基于Remoting的RealProxy,或者基于Emit实现的动态代理,或者基于反射的Attribute扫描拦截.但是我们还有另类的拦截方案DynamicObject,只要我们继承 ...
- BaseDao封装
1.lombok 1) 在pom.xml中导入依赖 <!--导入lombok--> <!-- https://mvnrepository.com/artifact/org.proje ...
- Codeforces Round #129 (Div. 1)E. Little Elephant and Strings
题意:有n个串,询问每个串有多少子串在n个串中出现了至少k次. 题解:sam,每个节点开一个set维护该节点的字符串有哪几个串,启发式合并set,然后在sam上走一遍该串,对于每个可行的串,所有的fa ...
- python爬虫-入门-了解爬虫
作为一个爬虫新手,我觉得首先要了解爬虫是的作用以及应用. 作用:通过爬虫获取网页内的信息.包括:标题(title)图片(image)链接(url)等等 应用:抽取所需信息,进行数据汇总及分析(从事网页 ...
- gulp打开gbk编码的html文件乱码
先上图,好忧伤: