Dre*_*her 16 c# mysql asp.net entity-framework entity-framework-4.1
我有一个使用Entity Framework 4.0访问的MySQL服务器.在数据库中,我有一个名为Works的表,其中有些是重要的.我用Asp.net开发网站.该表可以在同一时间再次使用.而这种情况会导致错误的启动问题.
我的代码是这样的:
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);
Run Code Online (Sandbox Code Playgroud)
如果一个以上的线程同时访问数据库,则仅保留最后一个更改.
电流输出:
t1:线程一 - t2:线程二
t1:访问工作
t2:访问工作
t2:访问不为空
t1:访问不为空
t1:计数已更改
t2:计数已更改
t1:保存更改
t2:保存更改
t1:当前计数:5
t2:当前计数:5
预期产出:
t1:访问工作
t2:访问工作
t2:访问不为空
t1:访问不为空
t1:计数已更改
t2:计数已更改
t1:保存更改
t2:保存更改
t1:当前计数:5
t2:当前计数:10
我知道为什么会遇到这个问题,因为这段代码不是原子的.我怎样才能改变原子操作?
Sla*_*uma 15
使用Entity Framework,您无法将其作为"原子"操作.你有以下步骤:
在这些步骤之间,另一个客户端可以从仍具有旧值的数据库加载实体.
处理这种情况的最佳方法是使用乐观并发.它基本上意味着如果计数器不再与您在步骤1中加载实体时的计数器不同,则不会保存步骤3中的更改.相反,您将获得可以通过重新加载实体和重新申请变更.
工作流程如下所示:
Work实体中,WordCount属性必须标记为并发令牌(如果是Code-First,则为注释或Fluent API)SaveChanges的try-catch块,赶上类型的异常DbUpdateConcurrencyExceptioncatch则从数据库重新加载块中的实体,再次应用更改并SaveChanges再次调用在本回答中,您可以找到此过程的代码示例(使用DbContext).
如果您在单个进程中托管您的网站,则下一个方法将起作用(它不适用于网络农场或网络加德森):
private static readonly Locker = new object();
void Foo()
{
lock(Locker)
{
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);
}
}
Run Code Online (Sandbox Code Playgroud)
您还可以做的就是通过 ObjectContext 使用原始 SQL 查询:
if (currentWork != null)
{
Console.WriteLine("Access is not null");
myEntity.ExecuteStoredCommand("UPDATE works SET WordCount = WordCount + 5 WHERE RID = @rid", new MySqlParameter("@rid", MySqlDbType.Int32){Value = 208)
Console.WriteLine("Count changed");
}
var record = myEntity.works.FirstOrDefault(xXx => xXx.RID == 208);
if(record != null)
Console.WriteLine("Current Count:" + record .WordCount);
Run Code Online (Sandbox Code Playgroud)