То, что вы пытаетесь сделать, - это обеспечить неоптимистичный параллелизм для ресурсов, к которым вы обращаетесь (в данном случае, к строкам базы данных).
Как правило, модели данных в .NET поддерживают только оптимистичный параллелизм (если вы вообще поддерживаете параллелизм), и большинство программ баз данных, которые вы видите в настоящее время, следуют той же тенденции.
При этом вам, вероятно, следует взглянуть на оптимистическую модель параллелизма, где у вас есть какая-то временная метка (будь то двоичное значение или дата, то, что меняется с каждым обновлением записи), которая сравнивается, когда Вы хотите выполнить операцию обновления.
Если идентификатор и отметка времени совпадают, операция завершается успешно, в противном случае она информирует пользователя, что кто-то еще обновил запись, и должна перезагрузить данные и попытаться обновить запись еще раз.
Следует отметить, что эта модель масштабируется намного лучше, чем любые неоптимистичные модели.
При этом, если вы действительно хотите неоптимистичную модель, вы должны подделать ее.
Как упоминалось выше, модели поставщиков данных .NET не поддерживают неоптимистичный параллелизм. Когда пользователь начинает операцию, он проверяет поле («заблокировано» или что-то в этом роде), чтобы увидеть, заблокирована ли запись в данный момент. Если он заблокирован, вы не разрешаете пользователю открывать форму для изменения данных. Если он НЕ заблокирован, вы разрешаете пользователю открывать форму и изменять данные.
Есть две важные вещи, которые вы должны сделать здесь. Во-первых, установите для «заблокированного» поля значение true, чтобы указать, что у вас есть блокировка.
Второе - убедиться, что вы работаете в транзакции при сравнении значения и обновлении заблокированного поля. Если вы этого не сделаете, существует возможность одновременного обновления поля двумя клиентами, а вы этого не хотите.
Лучший способ инкапсулировать это - иметь хранимую процедуру, которая принимает идентификатор записи, которую вы хотите заблокировать.
Затем выполняется обновление, например:
--- Update the table.
update <table> set locked = 1 where id = @id and locked = 0
--- Return the rowcount.
return @@rowcount
Следует отметить, что проверка в «заблокированном» поле очень важна, так как позволяет значению @@ rowcount быть либо 0, либо ненулевым (в зависимости от того, используются ли ваши идентификаторы или нет). являются уникальными), которые можно оценить как ложные в нулевом регистре и истинные в ненулевом регистре в коде приложения.
Затем в коде приложения вы завершаете транзакцию, и если значение равно true, вы открываете форму и позволяете пользователю редактировать, в противном случае вы сообщаете ему, что ему нужно подождать.
Когда пользователь завершает сохранение записи, он снова устанавливает бит «заблокирован» в ноль, опять же, в транзакции с другими операциями сохранения.
Единственным явным недостатком этого факта является то, что если ваше приложение падает после того, как пользователь заблокировал запись, оно никогда не станет разблокированным, и вам придется вручную перейти и удалить «заблокированный» бит.
С транзакциями и оптимистичным параллелизмом вам не нужно беспокоиться об этом, поэтому я бы еще раз настоятельно рекомендовал вам не использовать неоптимистическую модель параллелизма.