当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > ADO.NET Entity Framework 试水:并发

ASP.NET
使用函数传递参数来执行相应的数据库操作
如何实现在窗体和窗体之间进行传递数据
ASP.NET中文显示之两种解决方法
ASP.NET、JSP及PHP之间的抉择
ASP.NET 2.0发送电子邮件中存在的问题
谈谈HtmlControl与WebControl的区别与用途
从ASP.NET 1.1升级到ASP.NET 2.0要考虑的Cookie问题
通过系统配置来提高ASP.NET应用程序的稳定性
妙用ASP2.0中的URL映射改变网址
AJAX实现web页面中级联菜单的设计
ASP.NET跨页面传值技巧总结
再议ASP.NET DataGrid控件中的“添加新行”功能
Geometry 对象浅析
重构CollapsibleSplitter
如何利用.NET Framework使用RSS feed
ASP.NET获取IP与MAC地址的方法
在ASP.NET 2.0中使用样式、主题和皮肤
ASP.NET中为GridView添加删除提示框
ASP.NET 2.0,无刷新页面新境界
看看一个.net版对话框控件

ASP.NET 中的 ADO.NET Entity Framework 试水:并发


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-17   浏览: 243 ::
收藏到网摘: n/a

    提到数据库操作,特别是企业级的数据库应用,就不得不提一个多人操作时经常会产生的问题——并发冲突。本文首先来看一下什么是并发冲突,传统的并发冲突有现有的处理方式,最后,结合EF,看一个处理并发冲突的实例。
  
  一、要完成本文中的实例,您需要作如下准备:
  
  将Visual Studio 2008及.NET Framework 3.5升级到SP1。点击转到升级地址。
  安装SQL SERVER 2005,VS 2008中自带的EXPRESS版的SQL SERVER应该也可以用。
  下载并附加数据库:点击下载DemoDbV2。
  创建一个VB Console Application,并且取一个合适的名字(例如:Concurrency之类的)。注意,目标Framework要设置成3.5版。
  
  
  二、什么是并发冲突 
   
让我们来看一个跟取款相关的例子:某年某月某日某时某分,老王在A取款机取钱,他儿子小王同时在B取款机取钱(不要问我为什么这么巧^_^),他俩从同一个账号上取。于是就发生了如下一序列的操作: 
   
A取款机向中央数据库提问:这账上还有多少钱? 
   
B取款机向中央数据库询问:这账上还有多少钱? 
   
 中央数据库回答A取款机:2W。 
   
中央数据库回答B取款机:2W。 
   
然后,老王对A取款机说:我要取出1.5W。 
   
同时,小王对B取款机说:我要取出1.8W。 
   
A取款机就算了一下,2W-1.5W=0.5W>0,于是就吐出1.5W现金给了老王,并且准备告诉中央数据库,现在还剩0.5W啦。但是,就在它告诉中央数据库之前,发生了以下的事情: 
   
B取款机计算了一下,2W(此时,它还不知道余额已经成0.5W了,因为A取款机还没有告诉中央数据库)减去1.8W等于0.2W大于0,于是就吐出1.8W现金给了小王。然后,它当然也要知会中央数据库。 
   
中央数据库于是收到A取款机的消息,说,这个账号还剩0.5W,于是刷新余额为0.5W。然后又收到B取款机说还剩0.2W,于是,就刷新余额为0.2W。 
   
呵呵,于是,小王+老王的账户里一共存有2W元,结果老王取了1.5W元,小王取了1.8W元,账户里却还剩了0.2W元!~@#$%^& 
   
这就是一种并发冲突,由于同一时间有两个或者多个端在对同一数据进行操作,从而导致数据发生了错误。如果取款机真的以这样的方式来处理并发,那么,我现在就不写这片文章了——赶紧发动全家对表,说好了在某一时刻同时取钱去。

三、常见的并发冲突处理方式 
   
一般来说,我们把并发冲突处理方式归结为3类。 
   
第一类:放任不管方式;第二类:开放式并发处理方式;第三类:保守式并发处理方式。 
   
1. 放任不管方式: 
   
与其说这是一种处理并发冲突的方式,不如说,它是一种没有对并发冲突做任何处理的方式。但是在许多过去的系统里,由于没有考虑到多用户、网络应用等情况,这种"处理方式"还真存在于不少系统中。
  
  举例来说,A、B两人从数据库中获取了同一个笔记本的信息,例如:IBM ThinkPad T61吧。然后:A把牌子改成了:Lenovo ThinkPad,B把型号改成了T61 8890A24。然后,他们开始提交了。此时,如果A先提交,然后B提交,那么,最后的结果是:IBM ThinkPad T61 8890A24;反之,则变成Lenovo ThinkPad T61。
  
  总之一句话,谁最后提交谁老大。想像一下,如果A修改了1000个属性的值,B修改了1个属性的值,那么,对于先提交的A来说,这将是一个多么惨痛的打击:-)  

虽然这种放任不管的方式似乎不太负责任,但是,其处理性能却是相对较高的。 
    
2. 开放式并发处理 
  
开放式并发处理,老外叫做Optimistic Concurrency——乐观的并发。这种并发处理方式要求我们对并发抱有一种乐观的态度:百分之九十九点九九不会发生并发冲突,万一发生了,系统也能捕获到冲突,或者根据策略自动处理,或者,就提醒一下用户,让用户来决定是不是要继续提交。 
  
仍然用上面的例子来说这事儿:A、B两个人同时获取了笔记本的信息:IBM ThinkPad T61。然后……(此处跟上例做一样的修改,直到提交)此时,如果A先提交,那么,B提交的时候,系统会发现,哎哟,不好,有并发冲突了,就会抛个异常给B,让B知道,发生并发冲突了,然后,B就可以根据实际情况,选择相应的处理策略(比如,继续提交进行覆盖或者取消提交等等);相反,如果B先提交,那么,A提交时,就会得到相应的提醒。 
  
这样的并发处理方式,可以说在可靠性与性能上取得平衡,适合于对数据可靠性要求不是特别严格,需要较高的性能,并且不会大量发生并发的场合。 
   
3. 保守式并发处理 
   
这是最为严谨的一种并发冲突的处理方式。它把并发转化为了串行操作。 
   
例如,A从数据库中获取了笔记本信息:IBM ThinkPad T61,B也要对其进行修改,但此时由于A已经从数据库中将数据取出,因此,B被置于等待状态。直到A把数据修改完提交了,数据库数据更新为Lenovo ThinkPad T61了,此时,数据库才把数据给B,那么B就可以在Lenovo ThinkPad T61的基础上,把它修改为Lenovo ThinkPad T61 8890A24。而在B提交前,其它一切针对此记录的操作都得排除等着B。 
   
这样子当然非常理想,由于不存在并发,自然也就消除了并发冲突的问题。但是,这种锁也存在着较为隐蔽的风险:如果A修改了数据,一直不提交,或者A因为故障,没有办法提交,那么,其它所有的相关的操作,都将被阻碍住。因此,只有对数据准确性要求极高并且用户可以忍受等待的情况下,使用这种并发冲突的处理方法。