Tomas
Tomas

Reputation: 18087

EF preventing race condition

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();
   }
}

Upvotes: 0

Views: 1942

Answers (3)

TGlatzer
TGlatzer

Reputation: 6248

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

Upvotes: 0

Vladimir Perevalov
Vladimir Perevalov

Reputation: 4159

  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.

Upvotes: 0

Matthew
Matthew

Reputation: 25743

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"
);

Upvotes: 2

Related Questions