2013-11-25 45 views
0

我在我的应用程序中使用了EF 6 and Code First数据库解决方案。同一个应用程序在几台计算机上运行并访问相同的数据库。数据库中的一个整数字段将从这些应用程序更新,此字段的值会减少。代码如下,我认为这可能是竞态条件问题。你在这种情况下如何解决问题?EF预防竞争条件

public partial class CaContext 
{ 
    public override int SaveChanges() 
    { 
    var addedStatistics = ChangeTracker.Entries<Statistic>().Where(e => e.State == EntityState.Added).ToList().Select(p => p.Entity).ToList(); 

    var testOrders = GetUser.Orders.First(); 
    testOrders.Credits = testOrders.Credits - addedStatistics.Count; //Race condition here 


    return base.SaveChanges(); 
    } 
} 
+1

一个'DbContext' [不是线程安全的(http://stackoverflow.com/questions/6126616/is-dbcontext-thread-safe),所以竞争条件是最少的问题。 –

+0

请详细解释一下?! – Tomas

回答

2

一个选择是执行递减价值,而不是做一个读的更新语句,算,写。

Database.SqlCommand(
    @"UPDATE [CreditCount] 
    SET [Credits] = [Credits] - x 
    WHERE [UserID] = y" 
); 
0
  1. 我想看看整体设计并删除此类计数器。例如,您可以创建一个表格,每次保存更改时您将在其中添加新记录。您在那里设置计数,然后使用SUM查询获得总计。这将消除问题。

  2. 如果你真的想拥有这样一个领域,你可以创建一个存储过程并调用它。 SP将在数据库上运行,并将同步访问数据。

0

在事务范围内执行操作(可能需要设置正确的隔离级别)。所以刚收官的SaveChanges()调用到交易范围:

public void method() { 
    using(var transactionScope = new TransactionScope()) { 
     _context.SaveChanges(); 
    } 
} 

你会发现更多的位置:http://msdn.microsoft.com/en-us/data/dn456843#transactionScope

+0

隔离级别不会像这样工作。当他读取当前值时,他必须像HOLDLOCK一样添加表后。我确定这是否可以通过EF进行。 –