首页 新闻 赞助 找找看

讨论下,并发处理数据处理问题。(EF)

0
悬赏园豆:40 [已解决问题] 解决于 2013-12-27 14:38

在使用EF的时候会有个上下文,该上下文会帮助我们跟踪模型数据的修改,从而实现按需修改更新的目的。

但是现在下面问题是:

1、页面呈现的时候有个context1获取model给页面,当操作完model后传到后台创建context2来更新数据库,此时因为上下文不同所以无法跟踪model的修改情况,实现不了按需修改。

2、同时也可能存在A、B两个用户同时修改了模型数据,但是是修改不同的栏位。这时候就加了个版本号控制字段,但是这样不同栏位的修改也会被限制更新。

 

不知道各位是如何处理这种情况。我想到的解决方案如下:

1、context缓存下来,每次请求时根据一定机制找回原来的context,再修改到原模型中。实现按需修改。。。也会出现问题2的问题

2、当编辑Model2完提交后创建新的context2后,更新的时候加上where 版本号=的条件,若更新记录返回0,就从DB中查出数据……这种方案不行,会造成根据Model2按需修改,但是却是覆盖之前人员的数据。。。

 

貌似没想到好办法,只能用版本号限制整行的修改了。。。有木有办法实现在不同栏位的更新,就算不同版本号也能更新成功呢?或则你们又失眠比较好的并发控制办法

滴答的雨的主页 滴答的雨 | 老鸟四级 | 园豆:3681
提问于:2013-12-24 10:01
< >
分享
最佳答案
0

1、从 Context1 查询出 Model1(通常使用 ViewModel) 传给页面;

2、当操作完成后,Model1 传到后台创新 Context2;

3、根据 Model1 的主键从 Context2 中查询出 Model2;

4、使用 Model1 的已修改属性修改 Model2 的对应属性;

5、调用 Context2.SaveChanges 更新数据库;

注意你的 Model 需要添加“并发标识”(http://blog.sina.com.cn/s/blog_6b449b1f0100ssoy.html),EF 将使用乐观并发来控制更新。

收获园豆:35
Launcher | 高人七级 |园豆:45045 | 2013-12-24 10:33

应该有dto对象。现在加入ViewModel。按照你上面所述,是不是vm里面要保存原始值呢,不然怎么按照第4步中根据“已修改属性”去操作

滴答的雨 | 园豆:3681 (老鸟四级) | 2013-12-24 10:43

@滴答的雨(何雨泉): DbContext.DbSet<TEntity>,查询出 TEntity 后转换成 TViewModel 对象,TViewModel 可能包含部分或全部 TEntity 的属性,修改 TViewModel 的某些属性后,再将 TViewModel 与 TEntity 对应的属性赋值(不用管哪些属性修改过),赋值的过程中,TEntity 的属性的值与新值一样,则不会发生更新。比如:

public class TEntity

{

   private string _text;

    public string Text

{ get{return this._text;}

  {set { if(this._text != value) { this._text = value;}}}

}

}

Launcher | 园豆:45045 (高人七级) | 2013-12-24 11:22

@Launcher: 在第三部中查出的Model2中的版本标识是最新的,但是界面上的数据很可能已经是对应旧版本的字段了,比如A字段,已经被A用户编辑过了。这时A字段与Model2中的值不一样,被当做是编辑的话就会导致覆盖的问题了。

滴答的雨 | 园豆:3681 (老鸟四级) | 2013-12-24 11:38

@滴答的雨(何雨泉): EF 采用的是乐观并发(http://blog.sina.com.cn/s/blog_6b449b1f0100ssoy.html,请把这篇文章读懂了),如果 Model2 是数据库中被修改后再读取出来的,那么这时候使用 A 赋值就会覆盖;如果在 A 赋值给 Model2 之前,数据库中的值又发生了更改,那么更新不会成功,因为数据库中的“并发标识”变动了,同 Model2 读取出来前的不一样。你也可以在读取 Model1 的时候把“并发标识”保存下来传递到 ViewModel 中,这样再更新 Model2 时,同时赋值并发标识,由于不管是 Model2 中或数据库中发生了变动,那么两者的“并发标识”都会不同,更新也就不会发生。

再次请你把上面那篇文章中的示例代码读懂了,纸上谈兵浪费你很多时间,最好你自己写一遍,然后调试,观察程序的行为。

Launcher | 园豆:45045 (高人七级) | 2013-12-24 11:50

@Launcher: 我了接的

1、悲观并发:一开始就锁定记录,比如按订单编码锁定,解锁后别人才能编辑该订单。(解锁前只能read)

2、乐观并发:通过并发标识来做,在最后更新到数据库的时候才做冲突检查,通过这样来提高并发量

 

EF采用了“乐观并发”,现在再回到我最原始的问题,是不是只能控制到整行记录的串行并发修改。。。因为想知道是否有办法实现:两个用户修改了不同栏位,这是后面那个操作者的并发标识已经不一样了,能不能有机制判断我修改的不是相同栏位允许修改。。。还是说标识不一样,放弃后我要做什么呢,刷新下数据,让用户重新打单吗?

滴答的雨 | 园豆:3681 (老鸟四级) | 2013-12-24 12:10

@滴答的雨(何雨泉): "并发标识"是对一条记录而言的,所以无法控制到一条记录的某个字段。要实现按字段来区分,那你需要自己写代码,会很繁琐,也就是给每个字段都记录一个版本号,通过每个字段的版本号来控制(可以看一下 Microsoft SyncFramework 如何实现数据库同步的)。因此,这不现实,标准的做法是放弃修改,然后刷新数据,让用户重新提交订单。

Launcher | 园豆:45045 (高人七级) | 2013-12-24 13:13
其他回答(1)
0

对行控制,应该比较标准了,如果非要对比较高并发的字段进行控制,分表控制可行否?

收获园豆:5
Yu | 园豆:12980 (专家六级) | 2013-12-24 16:27
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册