如何在EF 条件下避免Oracle数据库脏读问题

如何在EF 条件下避免Oracle数据库脏读问题

1.问题说明

业务逻辑:一个零件有多个部件,如果这个零件的部件全部完工,则零件也可视为完工。
具体处理方式:我们为部件记录变更创建了触发器,每个部件完成状态变更后就会触发触发器,触发器中会根据部件对应的零件号查询未完工部件的数量,当数量为0时,更新零件的完工状态。
问题描述:实际情况是,有部分零件的部件即使全部完工,也没有将零件状态更新。

2.问题分析

如果是数据没有更新,有两种可能性,一种是触发器没有触发,另一种是触发器虽然执行了,但认为不满足完工条件。
我们在触发器中增加了日志记录,确认触发器确实触发了,同时发现一个有三根部件的零件,按理说应该未完工部件三次查询应该依次是2,1,0,一旦为0,则会立刻更新零件状态。而实际情况是,三次全部为2,所以零件状态没有更新。
当第一根部件提交时,查询应该是2。当第二根提交时,此时触发器才触发,再查询当然应该为1,怎么可能是2呢?
我们发现这三个部件用户是一次操作进行提交的,意味着我们提交时会放在一个事务里面处理,这个错误的产生就和Oracle的工作原理有关。
只要是在一个事务中进行update,这三次触发的trigger都会使用同一个SCN号(System Change Number)去数据库中进行查询,而SCN号代表着数据库中的时间。因此查询结果必然是一样的。其中第二、三次读取的是无效数据,称之为脏读。
因此,我们要在此处避免脏读,就必须让三次部件提交在三个事务中,这样就可以为触发器中的查询产生三个SCN号,进行三次不一样的查询。

3.问题解决

原来代码如下:会在批量部件在内存更新后,一起提交到数据库,数据库提交在循环外,属于一个事务,代码如下:
foreach (var partProcess in partProcessList)
{……}
context.SaveChanges();
最新代码如下:一方面将SaveChanges()放到了循环内,让每个部件直接提交,独享一个事务。同时发现Entity Framework太智能了,会多个SaveChanges()合并为一个事务提交,提高工作效率,但这也有违于我们的初衷,因此增加了独立的强行事务提交。
foreach (var partProcess in partProcessList)
{…
using (var dbContextTransaction = context.Database.BeginTransaction())
{
context.SaveChanges();
dbContextTransaction.Commit();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值