Подтвердить что ты не робот

Как вы управляете параллельным доступом к формам?

У нас есть набор форм в нашем веб-приложении, которым управляют несколько сотрудников. Формы являются общими для всех сотрудников. Сейчас мы реализовали механизм блокировки. Но проблема в том, что нет надежного способа узнать, когда пользователь вышел из системы, поэтому форму нужно разблокировать. Мне было интересно, есть ли лучший способ управлять одновременными пользователями, редактируя одни и те же данные.

4b9b3361

Ответ 1

Вы можете использовать оптимистичный concurrency, который представляет собой библиотеку данных .Net. Фактически вы предполагаете, что обычно никто не будет редактировать строку одновременно. Когда это происходит, вы можете либо выбросить сделанные изменения, либо попытаться создать более приятную логику повтора, когда у вас есть два пользователя, которые редактируют одну и ту же строку.

Если вы сохранили копию того, что было в строке, когда вы начали ее редактировать, а затем напишите свое обновление как:

Update Table set column = changedvalue 
where column1 = column1prev 
AND column2 = column2prev...

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

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

Ответ 2

Сделайте что-то похожее на то, что сделано во многих системах контроля версий. Разрешить кому-либо редактировать данные. Когда пользователь отправляет форму, база данных проверяется на наличие изменений. Если запись не была изменена до этого представления, разрешите ее, как обычно. Если оба изменения совпадают, игнорируйте входящее (теперь избыточное) изменение.

Если второе изменение отличается от первого, запись теперь находится в конфликте. Пользователю представлена ​​новая форма, которая указывает, какие поля были изменены конфликтующим обновлением. Затем пользователь должен решить конфликт (обновляя оба набора изменений) или разрешить существующему обновлению.

Ответ 3

Как предложил Спенс, вам нужно оптимистично concurrency. Стандартный веб-сайт, который не учитывает, изменились ли данные, использует то, что я называю "последние победы записи". Проще говоря, какое бы соединение ни связывалось с базой данных в последний раз, эта версия данных является той, которая хранится. В оптимистическом concurrency вы используете логику "первая запись выигрывает", так что если два соединения пытаются сохранить одну и ту же строку одновременно, первая, которая совершает победы, а вторая отклоняется.

Для этого механизма есть две части:

  • Правила, по которым вы не выполняете вторую фиксацию
  • Как система или пользователь обрабатывают отклоненную фиксацию.

Определение того, следует ли отклонять фиксацию

Два подхода:

  • Таблица сравнения, которая изменяется каждый раз, когда происходит фиксация
  • Сравните данные с их совершенной версией в базе данных.

В первую очередь подразумевается использование типа данных SQL Server rowversion, который гарантированно изменяется при каждом изменении строки. Поверхность заключается в том, что она упрощает сворачивание вашей собственной логики, чтобы определить, изменилось ли что-то. Когда вы получаете данные, вы извлекаете значение столбца rowversion, и когда вы совершаете фиксацию, вы сравниваете это значение с тем, что в настоящее время находится в базе данных. Если они отличаются друг от друга, данные изменились с тех пор, как вы последний раз их извлекли, и вы должны отклонить фиксацию, иначе продолжайте сохранять данные.

Второй вопрос заключается в сравнении столбцов, которые вы вытащили с их имеющимися зафиксированными значениями в базе данных. Как предложил Спенс, если вы попытаетесь обновить, а строки не будут обновлены, то, очевидно, один из критериев не удался. Эта логика может оказаться сложной, если некоторые значения равны нулю. Многие объектные реляционные сопоставители и даже технологии .NET DataTable и DataAdapter могут помочь вам справиться с этим.

Обработка отклоненной фиксации

Если вы не оставите это до пользователя, форма напишет какое-то сообщение о том, что данные изменились с момента последнего редактирования, и вы просто повторно загрузите данные, перезаписывающие их изменения. Как вы можете себе представить, пользователи не особенно любят это решение, особенно в системе с большим объемом, где это может происходить часто.

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


Концепция проверки эффективно пессимистична concurrency, где пользователи блокируют строки. Как вы обнаружили, это трудно реализовать в среде без гражданства. Пользователи печально известны тем, что просто закрывают свой браузер, когда у них что-то проверено или с помощью кнопки "Назад", чтобы вернуть набор, который был извлечен, и попытаться его возобновить. ИМО, это больше проблем, чем стоит попробовать пойти по этому пути в веб-решении. Предполагая, что вы пишете имя пользователя, последнее изменившее данную строку, с оптимистичным concurrency, вы можете сообщить пользователю, чьи изменения отклоняются, кто сохранил данные перед ними.

Ответ 4

Я видел, как это делалось двумя способами. Первый заключается в том, чтобы в таблице базы данных, связанной с этими данными, был столбец "проверен". Ваш сервис должен будет искать этот флаг, чтобы увидеть, будет ли он редактироваться. Этот срок может истекать после выполнения порогового значения времени (с помощью триггера), если пользователь не вносит изменений. Второй способ - иметь выделенную таблицу "проверенных", в которой хранятся имена идентификаторов и объектов (возможно, имя таблицы). Это будет работать одинаково, и теоретически вам будет меньше времени поиска. Однако я вижу проблемы concurrency, используя второй метод.

Ответ 5

Зачем вам нужен тайм-аут сеанса? Просто синхронизируйте доступ к своим данным (формам и т.д.) И этому. ОБНОВЛЕНИЕ: Если вы имеете в виду, что у вас есть "длинные транзакции", где форма заблокирована, как только пользователь открывает редактор (или что-то еще) и остается заблокированным до тех пор, пока пользователь не совершит изменения, выполните следующие действия:

  • используйте оптимистичную блокировку, реализуйте ее путем управления таблицей данных форм Оптимистическая блокировка
  • может привести к потере работы, если пользователь давно отсутствовал, а затем попытался зафиксировать его изменения и обнаружил, что кто-то еще уже обновил форму. В этом случае вы можете реализовать явную "блокировку" формы, когда пользователь "блокирует" форму, как только он начнет работать над ней. Другой пользователь заметит, что форма "заблокирована" и либо связывается с владельцем блокировки, чтобы решить проблему, либо он может "отменить" форму для себя, потеряв все обновления первого пользователя в процессе.

Ответ 6

Мы вводим очень простую оптимистичную схему блокировки, которая работает следующим образом:

  • каждая таблица имеет last_update_date поле в нем
  • когда форма создана last_update_date для записи хранится в скрытом поле ввода
  • когда форма отправляется сервером проверяет last_update_date в базы данных против даты в скрытое поле ввода.
  • Если они совпадают, то никто другой не изменил запись, так как форма была создана так система обновляет данные.
  • Если они не совпадают, то кто-то еще изменил запись, так как форма была создано. Система отправляет пользователя обратно на страницу редактирования формы и сообщает пользователю, что кто-то еще отредактировал запись, и они должны повторно применить их изменения.

Это очень просто и работает достаточно хорошо.

Ответ 7

Вы можете использовать столбец "timestamp" на вашей таблице. Refer: Каков таинственный тип данных timestamp в Sybase?

Я понимаю, что вы хотите избежать перезаписи существующих данных с последовательными обновлениями.

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

После изменения данных перед обновлением вы должны проверить столбцы "timestamp" (ваши и db), чтобы убедиться, что кто-то изменил данные во время редактирования.

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

Ответ 8

Самый простой способ - форматировать оператор обновления, чтобы включить дату и время, когда последняя запись была обновлена. Например:

UPDATE my_table SET my_column = new_val WHERE last_updated = <datetime when record was pulled from the db>

Таким образом, обновление будет успешным только в том случае, если никто не изменил запись с момента последнего чтения.

Вы можете сообщить пользователю о конфликте, проверив, произошло ли обновление после SELECT после UPDATE.