1.说明

  和EF版本的并发处理方案一致,需要知道乐观并发和悲观并发的区别,EF Core只支持乐观并发;监控并发的两种方案:监测单个字段和监测整条数据,DataAnnotations 和 FluentApi的两种配置方式。

 (PS:EF Core中的并发处理模式和EF中的基本类似,其他相关概念参考:第二十节: 深入理解并发机制以及解决方案(锁机制、EF自有机制、队列模式等):

 2. 两个概念

(1).悲观并发:比如有两个用户A,B,同时登录系统修改一个文档,如果A先进入修改,则系统会把该文档锁住,B就没办法打开了, 只有等A修改完,完全退出的时候B才能进入修改。

(2).乐观并发:A,B两个用户同时登录,如果A先进入修改紧跟着B也进入了。A修改文档的同时B也在修改,如果在A保存之后/ B再保存他的修改,此时系统检测到数据库中文档记录与B刚进入时不一致,B保存时会抛出异常,修改失败。

3. 监测单个字段

用到的表结构:

(1). 监测那个字段就配置哪个字段,有两种配置方式,如下:

  A. DataAnnotations配置:在对应字段上加特性 [ConcurrencyCheck]

  B. FluentApi配置: entity.Property(p => p.age).IsConcurrencyToken();

提交数据库的时候,发现该字段中的值已经被篡改了,就会进入DbUpdateConcurrencyException并发异常中,这里面可以获取三个值:数据库原始值、 数据库现在值、内存中当前值。

通常的处理方式:

  ①. Reload一下,放弃当前内存中的实体,重新到数据库中加载当前实体,然后用当前数据库中的值进行相应的业务处理。

  ②. 直接提示用户,信息被修改,请重新操作一遍(可以更友好的提示一下)

(2).案例:

  保证T_Concurrency01有一条id=01的记录(age=10),分别用上面的两种方式进行配置,测试的结果最终age=4,执行正确。

             {
//保证T_Concurrency01有一条id=01的记录(age=10)
ypfContext db1 = new ypfContext();
ypfContext db2 = new ypfContext(); try
{
var data1 = db1.T_Concurrency01.Where(u => u.id == "").FirstOrDefault();
var data2 = db2.T_Concurrency01.Where(u => u.id == "").FirstOrDefault(); data1.age = data1.age - ;
int result1 = db1.SaveChanges(); data2.age = data2.age - ;
int result2 = db2.SaveChanges(); //发现age的值和原先查出来的不一致,会抛异常进入cache
}
catch (DbUpdateConcurrencyException ex)
{
var entityEntry = ex.Entries.Single();
var original = entityEntry.OriginalValues.ToObject() as T_Concurrency01; //数据库原始值 10
var database = entityEntry.GetDatabaseValues().ToObject() as T_Concurrency01; //数据库现在值 8
var current = entityEntry.CurrentValues.ToObject() as T_Concurrency01; //当前内存值 6
entityEntry.Reload(); //放弃当前内存中的实体,重新到数据库中加载当前实体 current.age = database.age - ; //应该拿着当前数据库实际的值去处理,即8-4=4
entityEntry.CurrentValues.SetValues(current);
int result3 = db2.SaveChanges();
}
}

4. 监测整条数据

用到的表结构:

(1). 首先要给该表在数据库中加一个字段(任意命名即可),通常叫“timeStamp”或“rowVersion”,然后进行配置:

  A. DataAnnotations配置:在对应字段上加特性[Timestamp]

  B. FluentApi配置: entity.Property(e => e.rowVersion).IsRowVersion();

提交数据库的时候,发现该表中任意字段中的值被篡改了,就会进入DbUpdateConcurrencyException并发异常中,这里面可以获取三个值:数据库原始值、 数据库现在值、内存中当前值。

通常的处理方式:

  ①. Reload一下,放弃当前内存中的实体,重新到数据库中加载当前实体,然后用当前数据库中的值进行相应的业务处理。

  ②. 直接提示用户,信息被修改,请重新操作一遍(可以更友好的提示一下)

(2). 案例

  保证T_Concurrency02有一条id=01的记录(age=10),没别用上面的两种方式进行配置,还是用age来进行测试,测试的结果最终age=4,执行正确。

             {
//保证T_Concurrency02有一条id=01的记录(age=10)
ypfContext db1 = new ypfContext();
ypfContext db2 = new ypfContext(); try
{
var data1 = db1.T_Concurrency02.Where(u => u.id == "").FirstOrDefault();
var data2 = db2.T_Concurrency02.Where(u => u.id == "").FirstOrDefault(); data1.age = data1.age - ;
int result1 = db1.SaveChanges(); data2.age = data2.age - ;
int result2 = db2.SaveChanges(); //发现age的值和原先查出来的不一致,会抛异常进入cache
}
catch (DbUpdateConcurrencyException ex)
{
var entityEntry = ex.Entries.Single();
var original = entityEntry.OriginalValues.ToObject() as T_Concurrency02; //数据库原始值 10
var database = entityEntry.GetDatabaseValues().ToObject() as T_Concurrency02; //数据库现在值 8
var current = entityEntry.CurrentValues.ToObject() as T_Concurrency02; //当前内存值 6
entityEntry.Reload(); //放弃当前内存中的实体,重新到数据库中加载当前实体 current.age = database.age - ; //应该拿着当前数据库实际的值去处理,即8-4=4
entityEntry.CurrentValues.SetValues(current);
int result3 = db2.SaveChanges();
}
}

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 本人才疏学浅,用郭德纲的话说“我是一个小学生”,如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

第四节:EF Core的并发处理的更多相关文章

  1. ASP.NET MVC深入浅出(被替换) 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式 第三节: EF调用普通SQL语句的两类封装(ExecuteSqlCommand和SqlQuery ) 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性) 第十节: EF的三种追踪

    ASP.NET MVC深入浅出(被替换)   一. 谈情怀-ASP.NET体系 从事.Net开发以来,最先接触的Web开发框架是Asp.Net WebForm,该框架高度封装,为了隐藏Http的无状态 ...

  2. .Net Core+Angular6 学习 第四部分(EF Core(Code First))

    目的: 打算通过EF core 练习从database receive data 显示到UI. 1. 创建一个新的project Model.定义一个 base interface entity以及实 ...

  3. 第四节: EF调用存储过程的通用写法和DBFirst模式子类调用的特有写法

    一. 背景 上一个章节,介绍了EF调用两类SQL语句,主要是借助 ExecuteSqlCommand  和 SqlQuery 两个方法来完成,在本章节主要是复习几类存储过程的写法和对应的EF调用这几类 ...

  4. 第十四节: EF的三种模式(四) 之 原生正宗的 CodeFirst模式的默认约定

    一. 简介 1. 正宗的CodeFirst模式是不含有edmx模型,需要手动创建实体.创建EF上下文,然后生成通过代码来自动映射生成数据库. 2. 旨在:忘记SQL.忘记数据库. 3. 三类配置:On ...

  5. Entity Framework (EF) Core工具创建一对多和多对多的关系

     一. EntirtyFramework(EF)简介 EntirtyFramework框架是一个轻量级的可扩展版本的流行实体框架数据访问技术,微软官方提供的ORM工具让开发人员节省数据库访问的代码时间 ...

  6. 第五节:EF Core中的三类事务(SaveChanges、DbContextTransaction、TransactionScope)

    一. 说明 EF版本的事务介绍详见: 第七节: EF的三种事务的应用场景和各自注意的问题(SaveChanges.DBContextTransaction.TransactionScope). 本节主 ...

  7. 第一节:EF Core简介和CodeFirst和DBFirst两种映射模式(以SQLite和SQLServer为例)

    一. EF简介 1. 定义 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台的数据访问技术,它还是一种对象关系映射器(ORM),它使.NET 开发人员能够使用面向对 ...

  8. EntityFramework Core 运行dotnet ef命令迁移背后本质是什么?(EF Core迁移原理)

    前言 终于踏出第一步探索EF Core原理和本质,过程虽然比较漫长且枯燥乏味还得反复论证,其中滋味自知,EF Core的强大想必不用我再过多废话,有时候我们是否思考过背后到底做了些什么,到底怎么实现的 ...

  9. [翻译 EF Core in Action 2.1] 设置一个图书销售网站的场景

    Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...

随机推荐

  1. Linux操作:使用grep排除搜索的目录

    使用grep时,当一个目录下有一个包含很多文件的目录,但也不想搜索它,怎么办? 使用 --exclude-dir 选项. 单个目录示例: grep -rni 'http' --exclude-dir= ...

  2. 左右对齐Justify遇到的坑

    遇到的问题 这两天在开发一个病历的对外展示页面,设计稿上label是左右拉伸对齐的,显示效果如下: 怎么实现这种效果呢? 首先想到的是文字中间加空格,但是这种方式太low了,而且不太容易控制.网上查资 ...

  3. HTML网页实现flv视频播放

    一.HTML代码如下: <div id="player"></div> 二.JavaScript代码如下: <script src="htt ...

  4. 易语言 MD5生成

    下载MD5脚本 https://download.csdn.net/download/zhangxuechao_/10573121 添加脚本组件 定义常量 生成MD5

  5. Java程序员的魔法杖-Arthas 3.1.2版本发布了

    Arthas已经成为我日常运维.线上排查的必备之品,听说最近更新版本了,今天这篇文章看下又增加了什么新的能力. Arthas是Alibaba开源的Java诊断工具,深受开发者喜爱. Github:ht ...

  6. Spring Cloud 微服务实战笔记

    Spring Cloud 微服务实战笔记 微服务知识 传统开发所有业务逻辑都在一个应用中, 开发,测试,部署随着需求增加会不断为单个项目增加不同业务模块:前端展现也不局限于html视图模板的形式,后端 ...

  7. 黑白之间的FastFlux

    DNS请求 通常我们对一个域名进行DNS请求,尤其是A记录,一般在一段时间内是不变的,其结果的异同也就是可能因地域而得到不同的结果.当然这个结果可能是个集合,也可能是一个IP地址.因为我们要考虑到CD ...

  8. MySQL多实例安装、配置、启动(四)

    一.规划信息 系统信息: cat /etc/redhat-release CentOS Linux release (Core) # uname -r -.el7.x86_64 数据库规划 PORT: ...

  9. opencv 程序

    IplImage结构中的一个元素:struct _IplROI *roi; //图像感兴趣区域,当该值非空时,只对该区域进行处理 .   ROI :Region of Interest,表示感兴趣的区 ...

  10. Springboot测试类之@RunWith注解

    @runWith注解作用: --@RunWith就是一个运行器 --@RunWith(JUnit4.class)就是指用JUnit4来运行 --@RunWith(SpringJUnit4ClassRu ...