5

我需要对某些实体框架模型的某些字段进行原子操作检查值,如果其值为0,则将其增加。

我想到了交易,比如:

bool controlPassed = false;
using (TransactionScope scope = new TransactionScope())
{
    var model = ...ModelEntities.first_or_default(...)
    if (model.field == 0){
        ++model.field;
        ...saveChanges();
        controlPassed = true;
    }
    scope.Complete();
}
if (controlPassed)
{
    ...
    using (TransactionScope scope = new TransactionScope())
    {
        --model.field;
        ...saveChanges();
        scope.Complete();
    }
}

当然,一切都在try catch等等。

我的问题是:它将如何工作?

真的很难检查。我有多线程应用程序。

是否有可能,两个或更多线程会通过控制(检查field == 0并增加它)?

谁会在数据库(数据库、表、行、字段)中被阻止?

我不能让两个或多个线程controlPassed同时在一个部分。

4

1 回答 1

10

是否有可能,两个或更多线程将通过控制(检查该字段 == 0 并增加它)?

You have Serializable transaction (that is default for TransactionScope). It means that there can be two threads with field == 0 but immediately after that deadlock happens because transaction for the first thread holds a shared lock on the filed and transaction for the second thread holds another shared lock for the same field. Neither of these transaction can upgrade the lock to exclusive to save changes because they are blocked by shared lock in other transaction. I think same would happen for RepeatableRead isolation level.

If you change isolation level to ReadCommitted (the default for SaveChangeswithout TransactionScope when using MS SQL Server) the answer will be again yes but this time without deadlock because EF uses normal selects without any table hints - that means that no lock on record is held when select completes. Only save changes (modification) locks records until transaction commits or rolls back.

To lock record in ReadCommitted transaction with select you must use native SQL query and UPDLOCK (to lock record for update during select and held it until transaction ends) table hint. EF queries do not support table hints.

Edit: I wrote a long article about pessimistic concurrency which describes why your solution doesn't work and what must be changed to make it work correctly.

于 2012-09-26T12:31:32.933 回答