У меня проблема в следующем:
У меня есть таблица (просто пример) со следующими полями:
ID int
Value int
У меня есть метод IncreaseByFive (), который выполняет следующие действия:
method IncreaseByFive(int ID)
{
int value = GetValueFromDB(ID);
value = value + 5;
SaveValueToDB(value, ID);
}
Чего я хочу избежать, так это следующей ситуации:
- Пользователь A вызывает метод и получает значение (в настоящее время 5)
- Пользователь B вызывает метод и получает значение (в настоящее время 5)
- Пользователь A увеличивает значение на 5 (теперь 10)
- Пользователь B увеличивает значение на 5 (теперь 10)
- Пользователь A сохраняет значение (10)
- Пользователь B сохраняет значение (10)
Теперь запись имеет значение 10, когда она должна была быть 15.
То, что я хочу форсировать, таково:
- Пользователь A вызывает метод и получает значение (в настоящее время 5)
- Пользователь B вызывает метод, но должен ждать, потому что A уже вызвал его. (DIBS!)
- Пользователь A увеличивает значение (теперь 10)
- Пользователь B все еще ждет
- Пользователь A сохраняет значение (запись имеет значение 10)
- Пользователь B теперь может читать значение (10)
- Пользователь B увеличивает значение (15)
- Пользователь B сохраняет значение
Теперь запись имеет значение 15, и это результат, который я ищу.
В прошлом я решал эту проблему, используя статический класс и блокируя статический объект, созданный в конструкторе этого класса, таким образом направляя всю работу через один статический метод, что заставляет другие вызовы ждать в очереди , Боюсь, однако, что это не масштабируется.
Я также думаю, что наивысший уровень изоляции (сериализуемый) для транзакции тоже не сработает, потому что он разрешит чтение в шаге 2 нежелательного примера выше.
Полагаю, другое решение - создать собственную таблицу блокировок и записать там блокировки, но, похоже, это не обязательно.
Я разрабатываю этот проект с C # (3.5) и SQL Server 2008.
Что думает улей?