原子增量与实体框架 [英] Atomic Increment with Entity Framework
问题描述
我有一个MySQL服务器,我访问使用实体框架4.0。在数据库中,我有一个名为作品某些统计成表。我开发Web站点Asp.net。此表acccesable一个更多用户同时进行。而这种情况会导致错误的incerement问题。
I have a MySQL Server which I access using Entity Framework 4.0. In the database I have a table called Works into which some counts. I develop web site with Asp.net. This table acccesable one more user same time. And this situation causes wrong incerement problem.
我的code这样的:
dbEntities myEntity = new dbEntities();
var currentWork = myEntity.works.Where(xXx => xXx.RID == 208).FirstOrDefault();
Console.WriteLine("Access work");
if (currentWork != null)
{
Console.WriteLine("Access is not null");
currentWork.WordCount += 5;//Default WordCount is 0
Console.WriteLine("Count changed");
myEntity.SaveChanges();
Console.WriteLine("Save changes");
}
Console.WriteLine("Current Count:" + currentWork.WordCount);
如果不是线程访问多一个数据库的同时,只有最后的更改均保持不变。
If one more than thread access the database same time, only last changes remain.
电流输出:
T1:线程一 - T2:螺纹两个
T1:访问工作
T2:访问工作
T2:访问不为空
T1:访问不为空
T1:计数改为
T2:计数改为
T1:保存更改
T2:保存更改
T1:当前计数:5
t1: Current Count: 5
T2:当前计数:5
t2: Current Count: 5
期望输出:
T1:访问工作
T2:访问工作
T2:访问不为空
T1:访问不为空
T1:计数改为
T2:计数改为
T1:保存更改
T2:保存更改
T1:当前计数:5
t1: Current Count: 5
T2:当前计数:10
t2: Current Count: 10
我知道为什么apeear这个问题,因为这code是不是原子。我怎样才能把原子操作?
I know why apeear this problem, because this code is not atomic. How can i turn atomic operation?
推荐答案
通过实体框架,你不能让这个原子操作。你有步骤进行:
With Entity Framework you can't make this an "atomic" operation. You have the steps:
- 从数据库中加载实体
- 在内存计数器变更
- 保存改变实体数据库
在这些步骤之间的另一个客户端可以从仍然有旧值数据库加载的实体。
In between these steps another client can load the entity from the database which still has the old value.
要应对这种情况的最好方法是使用的乐观并发的。它主要是指如果计数器不一样了,这是当你加载在步骤1中的实体相反,你会得到,你可以通过重新加载实体处理异常和步骤3中的改变将不会被保存重新应用更改。
The best way to deal with this situation is to use optimistic concurrency. It basically means that the change in step 3 won't be saved if the counter is not the same anymore that it was when you loaded the entity in step 1. Instead you'll get an exception that you can handle by reloading the entity and reapplying the change.
工作流程是这样的:
- 在
工作
实体WORDCOUNT
属性必须被标记为并发令牌(注释或万一流利的API $的C $ C-前) - 从数据库中加载实体
- 在内存计数器变更
- 呼叫
的SaveChanges
在的try-catch
类型的块,并捕获异常DbUpdateConcurrencyException
- 如果发生异常重装在
抓实体
块从数据库中,再次申请变更并调用的SaveChanges
再次 - 重复最后一步,直到也不例外发生了
- In the
Work
entity theWordCount
property must be marked as a concurrency token (annotations or Fluent API in case of Code-First) - Load entity from database
- Change counter in memory
- Call
SaveChanges
in atry-catch
block and catch exceptions of typeDbUpdateConcurrencyException
- If an exception occurs reload the entity in the
catch
block from the database, apply the change again and callSaveChanges
again - Repeat the last step until no exception occurs anymore
在这个答案你可以找到这个程序一个code为例(使用的DbContext
)。
In this answer you can find an code example for this procedure (using DbContext
).
这篇关于原子增量与实体框架的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!