处理 EF 并发其实就这么简单
最近项目有点闲,终于可以了解点自己想了解的了,以前听同事讲面试的经历总会被问到“如何处理高并发大数据” 乍一听感觉这东西好像很有学问的样子,于是并发这个词在脑海里留深刻印像,而且在自己心中的技术地位也提高很多,也导致了解并发相关的知识时,也带着思想负担,总以为很难懂,程序员或许都是这样,在自己不懂的技术领域,别人说一个很简单的技术,给他的感觉都是很高深的样子,其实自己一了解就会发现,“哎哟 我 C 原来就这样儿啊!”总之只要你想了解,花点时间就没有难的事! 好了 正式进入正题
EF并发处理 在此之前先把与并发相关的一此知识点给大家介绍一下,有些虽然不是了解并发的必要条件,但我认为多了解一点又有什么不好呢?
一 EF并发介绍
什么叫并发:当多个用户同时更新同一数据的时候,由于更新可能导致数据的不一致性,使得程序的业务数据发生错误,这种情况可以称之为并发。
并发又分为两种:乐观并发 与 悲观并发
乐观并发:即系统允许多个用户同时修改同一条记录,系统会预先定义由数据并发所引起的并发异常处理模式,去处理修改后可能发生的冲突
当出现乐观并发时应该怎么处理呢,通常有如下三种处理方法
a 保留最后一次对象修改的值
b 保留最初的修改值
c 合并修改值
这三种处理方法下文会一一介绍
悲观并发:在同一时刻只允许一个用户修改相同数据,直接用Lock 与 unLock就可以处理,后文就不再解释了
二 EF对象状态
在EF中所有的对象状态只有被添加到ObjectContext 上下文中才能被跟踪,才能进行持久化操作,那么在ObjectContext中对于对象状态分几种呢?有如下五种
三 EF事务隔离级别
在这里只例举三个最常用到的隔离级别,其它的有待朋友们自己行研究了
ReadCommitted:不可以在事务期间读取可变数据,但是可以修改它(EF 默认的隔级别)
ReadUncommitted:可以在事务期间读取和修改可变数据。
Serializable:可以在事务期间读取可变数据,但是不可以修改,也不可以添加任何新数据。
随着隔离级别的提高,可以更有效地防止数据的不一致性。但是,这将降低事务的并发处理能力,会影响多用户访问
四 事务不同隔离级别带来数据读取的不同结果
脏读:当一个事务读取数据修改后以经SaveChange但事务还没有提交,此时另外一个事务就读取了该数据,此时的数据就是脏数据,这一过程就是脏读
不可重复读:是指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的这一过程就是不可重复读
幻读:一个事务针对一张表的所有数据进行读取修改,而此时另一个事务向表中插入了一条数据,则第一个事务数据不包含新数据,像出现幻觉一样,这一过程就是幻读
ReadCommitted 会引发 不可重复读 和幻读
ReadUncommitted 会引发 脏读 ,不可重复读 和幻读
Serializable 以上三种都不会发生
可见 Serializable的隔离级别是最高的,数据也是最准确的,但是高正确率也是要付出代价的,在此种隔离级别下,读取数据,与更新数据的效率也是最低的
五 EF并发的处理流程
对于并发原理是这样的,每一次操作表 字段TimeStamp的值都会改变,而每次对表做操作时都会比对对象的TimeStamp值与数据库中表的值是否相同,是则操作表,否 ,则抛出异常给客户端或是刷新对象状态后重新保存,详细步骤如下
1 在表中新建一个字段类型为TimeStamp , TimeStamp类型在.netFrameWork中是一个8位的数组,在SQL中则是一串二进制字符
2 在.edmx 对象实体模型图中,右键TimeStamp字段 属性-->并发模式-->选择Fixed
注意:把并发模式 设为Fixed后每一次操作表都会把TimeStamp字段当做条件查询,只有相等才能成功,以下是用SQL Profile跟踪到的结果 在 where 处可以看到效果
3 模拟并发,通过捕获异常在异常处返回消息给客户端 异常类型有如下两种
//第一次加载对象更新后暂不保存到数据库
var fContext = new BolgModelEntities();
var menuObj = fContext.Menu.FirstOrDefault();
menuObj.MenuName = "C#"; using (var sContext = new BolgModelEntities())
{
//第二次加载对象更新后,保存到数据库 此时TimeStamp的值已改变,与menuObj对象的TimeStamp值已不同,所以在menuObj保存时会抛异常出来
var obj = sContext.Menu.FirstOrDefault();
obj.MenuName = "WPF";
sContext.SaveChanges();//可以顺利保存
} try
{
//保存会抛异常,因为TimeStamp 值不匹配
fContext.SaveChanges();
}
//catch (DbUpdateConcurrencyException ex) //EF 自定义异常
//{ // fContext.Refresh(RefreshMode.ClientWins, menuObj);
// fContext.SaveChanges();
//}
catch (System.Data.OptimisticConcurrencyException ex) //.net FreamWork 定义异常
{
//捕获异常后依然对数据进行保存
fContext.Refresh(RefreshMode.ClientWins, menuObj); // RefreshMode.ClientWins 保存对象更新后的值 且对象的状态为Modified。 fContext.Refresh(RefreshMode.StoreWins, menuObj);//RefreshMode.StoreWins 保存数据库中原有值, 且对象的状态为Modified fContext.SaveChanges();//SaveChanges完成后对象状态变为Unchanged }
catch (System.Data.OptimisticConcurrencyException ex)
{
//捕获异常后不再处理,将消息返回给客户端
string message = string.Empty;
message = "出现数据冲突请重新提交";
return message;
}
在并发抛出异常后可以根据业务需,向客户端返回消息,
也可以直接处理冲突后的数据
a 保留最后一次对象修改的值 用 RefreshMode.ClientWins
b 保留最初的修改值 用 RefreshMode.StoreWins
c 合并修改值 针对同对象不同属性一样可以 用 RefreshMode.StoreWins
好了到此 关于EF的并发就写完了,当然我只是把并发的基础说了一下,对于更高效,科学的并发,还需要朋友根据自己项目 的情况来做相应的处理
其实 写完了才发现关于EF的并发 其实并没有想象中的那么麻烦,只要多花点时间,多看看资料,问题就不大了
对于以上内容,如有不对之处,还望各位能指出,不要让我误导了他人,
另外如果觉得,本文对你有那么一点帮助,还望不吝啬的点一点 推荐,您的推荐将是我源源不断的写作力!
处理 EF 并发其实就这么简单的更多相关文章
- MVC3+EF4.1学习系列(七)-----EF并发的处理
看这篇文章之前 推荐园子里的 这个文章已经有介绍了 而且写的很好~~ 可以先看下他的 再看我的 并发 1.悲观并发 简单的说 就是一个用户访问一条数据时 则把这个数据变为只读属性 把该数据变为独占 ...
- 用EF DataBase First做一个简单的MVC3报名页面
使用EF DataBase First做一个简单的MVC3报名网站 ORM(Object Relational Mapping)是面向对象语言中的一种数据访问技术,在ASP.NET中,可以通过ADO. ...
- 一步一步学EF系列一【最简单的一个实例】
整个文章我都会用最简单,最容易让人理解的方式给大家分享和共同学习.(由于live Writer不靠谱 又得补发一篇) 一.安装 Install-Package EntityFramework 二.简单 ...
- Java并发(10)- 简单聊聊JDK中的七大阻塞队列
引言 JDK中除了上文提到的各种并发容器,还提供了丰富的阻塞队列.阻塞队列统一实现了BlockingQueue接口,BlockingQueue接口在java.util包Queue接口的基础上提供了pu ...
- 在EF中使用SQL执行简单高效的增删查操作
随着平台数据的积累,对于数据访问的速度要求愈来愈高.优化后台访问性能,将是之后的一个重点任务. 但是,后台在项目开发初期采用的是Abp(Lite DDD)框架,集成EnityFramework.因为之 ...
- golang实现并发爬虫二(简单调度器)
上篇文章当中实现了单任务版爬虫. 那么这篇文章就大概说下,如何在上一个版本中进行升级改造,使之成为一个多任务版本的爬虫.加快我们爬取的速度. 话不多说,先看图: 其实呢,实现方法就是加了一个sched ...
- ASP.NET Core MVC+Layui使用EF Core连接MySQL执行简单的CRUD操作
前言: 本章主要通过一个完整的示例讲解ASP.NET Core MVC+EF Core对MySQL数据库进行简单的CRUD操作,希望能够为刚入门.NET Core的小伙伴们提供一个完整的参考实例.关于 ...
- Java并发:ThreadLocal的简单介绍
作者:汤圆 个人博客:javalover.cc 前言 前面在线程的安全性中介绍过全局变量(成员变量)和局部变量(方法或代码块内的变量),前者在多线程中是不安全的,需要加锁等机制来确保安全,后者是线程安 ...
- MVC中使用EF增删改查,简单的例子
//这个是分页数据和总页数类 public class SummaryBase<TModel> { public SummaryBase(); public IList<TModel ...
随机推荐
- Lazy<T>在Entity Framework中的性能优化实践(附源码)
在使用EF的过程中,导航属性的lazy load机制,能够减少对数据库的不必要的访问.只有当你使用到导航属性的时候,才会访问数据库.但是这个只是对于单个实体而言,而不适用于显示列表数据的情况. 这篇文 ...
- Mongodb Manual阅读笔记:CH3 数据模型(Data Models)
3数据模型(Data Models) Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作Mongodb Manual阅读笔记:CH3 数据模型(Data Models)Mon ...
- .NET领域驱动设计—实践(穿过迷雾走向光明)
阅读目录 开篇介绍 1.1示例介绍 (OnlineExamination在线考试系统介绍) 1.2分析.建模 (对真实业务进行分析.模型化) 1.2.1 用例分析 (提取系统的所有功能需求) 1.3系 ...
- 《CLR via C#》读书笔记--基元类型、引用类型和值类型
编程语言的基元类型 编译器直接支持的数据类型称为基元类型.基元类型直接映射到Framework类库中存在的类型.例如:C#中的int直接映射到System.Int32类型.下表给出了C#基元类型与对应 ...
- SQL Server 2008 R2——ROW_NUMBER() 去掉不同行中相同列的重复内容
==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...
- Python基础之set与函数
set集合 set 是无序,不重复的序列,基本功能包括去重和关系测试,集合中没有插入的方法,只能添加. 集合对象还支持union(联合), intersection(交), difference(差) ...
- Confluence自启动脚本
由于confluence用rc.local是无法自启动的,所以这里附上confluence的启动脚本 将以下脚本拷贝到/etc/init.d/confluenced # cd /etc/init.d/ ...
- webstorm 10 配置
小弟以前都是用sublime,sublime是一款轻量级的文本编辑器.但是现在要隆重介绍的前端开发工具webstorm,为什么说它是前端开发工具,而不是前端开发编辑器呢?它具备的功能,不只只是编辑器这 ...
- 学习shell中遇到的一些基础问题总结
今天入门Shell脚本编程:今天的目标是完成冒泡排序,遇到了很多问题,总结了一下: 我从c转到shell遇到了这样的一些情况: 1:首先这几个符号非常重要 $变量:把变量的值拿出来使用(所以赋值语句应 ...
- Spring学习之AOP总结帖
AOP(面向方面编程),也可称为面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP). 在进行 OOP 开发时,都是基于对组件(比如类)进行开发,然后对组件进行组 ...