Вызов чур в строке стола - PullRequest
1 голос
/ 01 апреля 2009

У меня проблема в следующем:

У меня есть таблица (просто пример) со следующими полями:

ID int
Value int

У меня есть метод IncreaseByFive (), который выполняет следующие действия:

method IncreaseByFive(int ID)
{    
    int value = GetValueFromDB(ID);
    value = value + 5;
    SaveValueToDB(value, ID);    
}

Чего я хочу избежать, так это следующей ситуации:

  1. Пользователь A вызывает метод и получает значение (в настоящее время 5)
  2. Пользователь B вызывает метод и получает значение (в настоящее время 5)
  3. Пользователь A увеличивает значение на 5 (теперь 10)
  4. Пользователь B увеличивает значение на 5 (теперь 10)
  5. Пользователь A сохраняет значение (10)
  6. Пользователь B сохраняет значение (10)

Теперь запись имеет значение 10, когда она должна была быть 15.

То, что я хочу форсировать, таково:

  1. Пользователь A вызывает метод и получает значение (в настоящее время 5)
  2. Пользователь B вызывает метод, но должен ждать, потому что A уже вызвал его. (DIBS!)
  3. Пользователь A увеличивает значение (теперь 10)
  4. Пользователь B все еще ждет
  5. Пользователь A сохраняет значение (запись имеет значение 10)
  6. Пользователь B теперь может читать значение (10)
  7. Пользователь B увеличивает значение (15)
  8. Пользователь B сохраняет значение

Теперь запись имеет значение 15, и это результат, который я ищу.

В прошлом я решал эту проблему, используя статический класс и блокируя статический объект, созданный в конструкторе этого класса, таким образом направляя всю работу через один статический метод, что заставляет другие вызовы ждать в очереди , Боюсь, однако, что это не масштабируется.

Я также думаю, что наивысший уровень изоляции (сериализуемый) для транзакции тоже не сработает, потому что он разрешит чтение в шаге 2 нежелательного примера выше.

Полагаю, другое решение - создать собственную таблицу блокировок и записать там блокировки, но, похоже, это не обязательно.

Я разрабатываю этот проект с C # (3.5) и SQL Server 2008.

Что думает улей?

1 Ответ

0 голосов
/ 01 апреля 2009

Может быть, я более недооцениваю это, но разве вы не просто оберните весь логический блок ..

  • прочитайте значение
  • записать значение

в транзакции базы данных соответствующего уровня ?

SET TRANSACTION ISOLATION LEVEL
    { READ UNCOMMITTED
    | READ COMMITTED
    | REPEATABLE READ
    | SNAPSHOT
    | SERIALIZABLE
    }
[ ; ]
...