Entity Framework 并发处理
什么是并发?
并发分悲观并发和乐观并发。
悲观并发:比如有两个用户A,B,同时登录系统修改一个文档,如果A先进入修改,则系统会把该文档锁住,B就没办法打开了,只有等A修改完,完全退出的时候B才能进入修改。
乐观并发:同上面的例子,A,B两个用户同时登录,如果A先进入修改紧跟着B也进入了。A修改文档的同时B也在修改。如果在A保存之后B再保存他的修改,此时系统检测到数据库中文档记录与B刚进入时不一致,B保存时会抛出异常,修改失败。
EF中如何控制并发?
Entity Framework不支持悲观并发,只支持乐观并发。
如果要对某一个表做并发处理,就在该表中加一条Timestamp类型的字段。注意,一张表中只能有一个Timestamp的字段。
Data Annotations中用Timestamp来标识设置并发控制字段,标识为Timestamp的字段必需为byte[]类型。

public class Person
{
public int PersonId { get; set; }
public int SocialSecurityNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}

Fluent API用IsRowVersion方法
modelBuilder.Entity<Person>().Property(p => p.RowVersion).IsRowVersion();
我们看到生成的数据库中,RowVersion是timestamp类型。

下面我们写一段代码来测试一下:

static void Main(string[] args)
{
var person = new Person
{
FirstName = "Rowan",
LastName = "Miller",
SocialSecurityNumber = 12345678
};
//新增一条记录,保存到数据库中
using (var con = new BreakAwayContext())
{
con.People.Add(person);
con.SaveChanges();
} var firContext = new BreakAwayContext();
//取第一条记录,并修改一个字段:这里是修改了FirstName
//先不保存
var p1 = firContext.People.FirstOrDefault();
p1.FirstName = "Steven"; //再创建一个Context,同样取第一条记录,修改LastName字段并保存
using (var secContext = new BreakAwayContext())
{
var p2 = secContext.People.FirstOrDefault();
p2.LastName = "Francis";
secContext.SaveChanges();
}
try
{
firContext.SaveChanges();
Console.WriteLine(" 保存成功");
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine(ex.Entries.First().Entity.GetType().Name + " 保存失败");
}
Console.Read();
}

上面我们实例化了三个DbContext,第一个增加一条记录到数据库中,第二个修改刚增加的记录但不保存,然后第三个Context也取刚新增的记录并保存,最后再保存第二个Context,结果保存失败。

可以看到我们的并发控制取到了作用。
分析EF生成的SQL语句:
exec sp_executesql N'update [dbo].[People]
set [LastName] = @0
where (([PersonId] = @1) and ([RowVersion] = @2))
select [RowVersion]
from [dbo].[People]
where @@ROWCOUNT > 0 and [PersonId] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8)',@0=N'Francis',@1=1,@2=0x00000000000007D1
可以看到,它在取对应记录的时候把RowVersion也作为筛选条件。上面例子中的secContext保存的时候,数据库中的RowVersion字段的值就变了,所以firContext保存的时候用原来的RowVersion取值,自然就取不到相应的记录而报错。
如果我们只是要对某个字段作并发控制呢?别着急,EF也有办法。
Data Annotations中用ConcurrencyCheck来标识

public class Person
{
public int PersonId { get; set; }
[ConcurrencyCheck]
public int SocialSecurityNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public byte[] RowVersion { get; set; }
}

Fluent API用IsConcurrencyToken方法
modelBuilder.Entity<Person>().Property(p => p.SocialSecurityNumber).IsConcurrencyToken();
上面的实体中,我们将SocialSecurityNumber(社会保险号)标识为开放式并发,也写一个类似的代码测试一下:

static void Main(string[] args)
{
var person = new Person
{
FirstName = "Rowan",
LastName = "Miller",
SocialSecurityNumber = 12345678
};
//新增一条记录,保存到数据库中
using (var con = new BreakAwayContext())
{
con.People.Add(person);
con.SaveChanges();
} var firContext = new BreakAwayContext();
//取第一条记录,并修改SocialSecurityNumber字段
//先不保存
var p1 = firContext.People.FirstOrDefault();
p1.SocialSecurityNumber = 123; //再创建一个Context,同样取第一条记录,
//修改SocialSecurityNumber字段并保存
using (var secContext = new BreakAwayContext())
{
var p2 = secContext.People.FirstOrDefault();
p2.SocialSecurityNumber = 456;
secContext.SaveChanges();
}
try
{
firContext.SaveChanges();
Console.WriteLine(" 保存成功");
}
catch (DbUpdateConcurrencyException ex)
{
Console.WriteLine(ex.Entries.First().Entity.GetType().Name + " 保存失败");
}
Console.Read();
}


运行结果同样是保存失败,说明我们的并发控制起作用了。
分析一下EF执行的SQL:
exec sp_executesql N'update [dbo].[People]
set [SocialSecurityNumber] = @0
where (([PersonId] = @1) and ([SocialSecurityNumber] = @2))
',N'@0 int,@1 int,@2 int',@0=123,@1=1,@2=12345678
可以看到,EF将我们要并发控制的列SocialSecurityNumber也作为一个筛选条件,这样firContext保存的时候也会因为的数据库中SocialSecurityNumber值变了,取不到对应的记录而更新失败。
补充一下:如果是EDMX如何将字段设置为Concurrency。很简单,在对应的字段上右键-属性。在打开的属性窗口中有一个并发模式,你将它选择为Fixed即可。

Entity Framework 并发处理的更多相关文章
- C# Entity Framework并发处理
原网站:C# Entity Framework并发处理 在软件开发过程中,并发控制是确保及时纠正由并发操作导致的错误的一种机制.从 ADO.NET 到 LINQ to SQL 再到如今的 ADO.NE ...
- [转]C#综合揭秘——Entity Framework 并发处理详解
本文转自:http://www.cnblogs.com/leslies2/archive/2012/07/30/2608784.html 引言 在软件开发过程中,并发控制是确保及时纠正由并发操作导致的 ...
- C#综合揭秘——Entity Framework 并发处理详解
引言 在软件开发过程中,并发控制是确保及时纠正由并发操作导致的错误的一种机制.从 ADO.NET 到 LINQ to SQL 再到如今的 ADO.NET Entity Framework,.NET 都 ...
- Entity Framework 并发处理(转)
什么是并发? 并发分悲观并发和乐观并发. 悲观并发:比如有两个用户A,B,同时登录系统修改一个文档,如果A先进入修改,则系统会把该文档锁住,B就没办法打开了,只有等A修改完,完全退出的时候B才能进入修 ...
- Entity Framework 并发处理借鉴
如下博客 http://www.cnblogs.com/Bce-/p/3725868.html
- Entity Framework 乐观并发控制
一.背景 我们知道,为了防止并发而出现脏读脏写的情况,可以使用Lock语句关键字,这属于悲观并发控制的一种技术,,但在分布式站点下,锁的作用几乎不存在,因为虽然锁住了A服务器的实例对象,但B服务器上的 ...
- C#:ORM--实体框架EF(entity framework)(1)
本文来自:http://www.cnblogs.com/xuf22/articles/5513283.html 一.什么是ORM ORM(Object-relational mapping),中文翻译 ...
- Entity Framework 项目使用心得
在博客园很久了,一直只看不说,这是发布本人的第一个博客. 总结一下在项目中,EntityFramework使用的一下经验拿来和大家分享,希望对大家有用~ 1. 在Entity Fram ...
- Entity Framework知识小总结
什么是Entity Framework EF是微软主推的数据存取技术,在实际开发中,现在通常使用EF来构建应用程序的数据存取层,它是一个开源的“对象/关系映射(ORM:Object Relationa ...
随机推荐
- EXPLAIN句法 优化表结构
EXPLAIN tbl_name or EXPLAIN SELECT select_options EXPLAIN tbl_name是DESC[RIBE] tbl_name或SHOW COLUMNS ...
- oracle 行转列 分析函数
oracle 行转列 首先看一下源数据: 方法一:WM_CONCAT group by 这个方法没有问题. SELECT CODE_TS, WMSYS.WM_CONCAT(S_NUM + || ':' ...
- 解决.net定时器在iis7上不执行问题
今天第一次在博客园发帖,以前一直在潜水,在这里也是学了不少东西.感谢各位园友 废话不多说,这也是我工作中遇到的问题: protected void Application_Start(object s ...
- EXTJS 4.2 资料 控件之checkboxgroup的用法(动态数据)
在开发中遇到两种情况:第一在新增窗体时,要动态加载CheckBox项:第二在修改时不但需要加载所有CheckBox项,还要并且选中之前新增时的选项 如图这是在修改页面的效果: 1.在新增窗体中动态加载 ...
- CrackMe_001
本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注册机的东西. 其中,文章中按照如下逻辑编排(解决如 ...
- css3属性整理
浏览器内核:主流内容主要有Mozilla(熟悉的有Firefox,Flock等浏览器).WebKit(熟悉的有Safari.Chrome等浏览器).Opera(Opera浏览器).Trident(讨厌 ...
- linux命令补全 忘记命令只记得开头
linux的shell不仅提供上下箭头来翻阅历史使用过的命令,还提供命令补全功能. 例如,你想创建一个文件夹,只记得是m开头的命令,此时可以: ①输入m ②按键盘上的Tab键两次 (有可能还出现这句话 ...
- PHP开发工具介绍之zendStudio
1.PHP开发工具介绍之zendStudio 下载:进入官网:http://www.zend.com/en/products/studio 选择下载安装 注意这里的工作空间要和你Apache的工作目录 ...
- spring IOC容器实例化Bean的方式与RequestContextListener应用
spring IOC容器实例化Bean的方式有: singleton 在spring IOC容器中仅存在一个Bean实例,Bean以单实例的方式存在. prototype 每次从容器中调用Bean时, ...
- asp.net 母版页使用详解--转
http://www.cnblogs.com/_zjl/archive/2011/06/12/2078992.html 母版页是VS2005中新引入的一个概念,它很好地实现界面设计的模块化,并且实现实 ...