0

I am using EF 6 and Code First database solution in my application. The same application runs on several computers and access the same database. One Integer field in database is updated from these applications, the value of this field is reduced. The code is below and I think here could be race condition problem. How do you solve the problem in this situation?

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();
   }
}
Tomas
  • 17,551
  • 43
  • 152
  • 257

3 Answers3

2

One option would be to perform an update statement that decrements the value instead of doing a read, calculate, write.

Database.SqlCommand(
  @"UPDATE [CreditCount] 
    SET [Credits] = [Credits] - x 
    WHERE [UserID] = y"
);
Matthew
  • 24,703
  • 9
  • 76
  • 110
0
  1. I would look at the overall design and remove such counter. For example, you can create a table, where you will add a new record everytime you save changes. You set the count there and then with a SUM query you get the total. This will eliminate the problem.

  2. If you really want to have such one field, than you can create a stored proc and call it. SP will be run on database and will have synchronized access to data.

Vladimir Perevalov
  • 4,059
  • 18
  • 22
0

Perform your operations inside of an Transaction Scope (possibly you have to set the correct isolation level). So just wrap up the SaveChanges() Call into an transaction scope:

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

You will find more here: http://msdn.microsoft.com/en-us/data/dn456843#transactionScope

TGlatzer
  • 5,815
  • 2
  • 25
  • 46
  • Isolation level will not work just like this. He would have to add table hind like HOLDLOCK when he reads the current value. I'm sure if this is possible via EF. – Vladimir Perevalov Nov 25 '13 at 14:57