Вызов Dibs в строке таблицы
-
22-08-2019 - |
Вопрос
У меня проблема в следующем:
У меня есть таблица (просто пример) со следующими полями:
ID int
Value int
У меня есть метод увеличенияByFive(), который делает следующее:
method IncreaseByFive(int ID)
{
int value = GetValueFromDB(ID);
value = value + 5;
SaveValueToDB(value, ID);
}
Чего я хочу избежать, так это следующей ситуации:
- Пользователь А вызывает метод и получает значение (в настоящее время 5).
- Пользователь Б вызывает метод и получает значение (в настоящее время 5)
- Пользователь А увеличивает значение на 5 (теперь 10)
- Пользователь Б увеличивает значение на 5 (теперь 10)
- Пользователь А сохраняет значение (10)
- Пользователь Б сохраняет значение (10)
Теперь запись имеет значение 10, хотя должно было быть 15.
Я хочу заставить следующее:
- Пользователь А вызывает метод и получает значение (в настоящее время 5).
- Пользователь Б вызывает метод, но ему приходится ждать, потому что А уже вызвал его.(Бабки!)
- Пользователь А увеличивает значение (теперь 10)
- Пользователь Б все еще ждет
- Пользователь А сохраняет значение (запись имеет значение 10)
- Пользователь B теперь может прочитать значение (10).
- Пользователь Б увеличивает значение (15)
- Пользователь Б сохраняет значение
Теперь запись имеет значение 15, и это именно тот результат, который я ищу.
Раньше я решал эту проблему, используя статический класс и блокируя статический объект, созданный в конструкторе этого класса, таким образом направляя всю работу через один статический метод, который заставляет другие вызовы ждать в очереди.Однако я боюсь, что это невозможно масштабировать.
Я также думаю, что самый высокий уровень изоляции (сериализуемый) для транзакции также не поможет, потому что он позволит чтение на шаге 2 нежелательного примера выше.
Я полагаю, что другим решением было бы создать собственную таблицу блокировок и записывать туда блокировки, но, похоже, в этом нет необходимости.
Я разрабатываю этот проект с помощью C# (3.5) и SQL Server 2008.
Что думает коллективный разум?
Решение
Может быть, я надобдумывая это, но не могли бы вы просто обернуть весь логический блок?..
- прочитать значение
- записать значение
в транзакции базы данных соответствующий уровень?
SET TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SNAPSHOT
| SERIALIZABLE
}
[ ; ]