ADO.NET. Управление базами данных. Связь по схеме OLE DB провайдера. Коррекция стилей DataGridView, страница 10

·  При внесении изменений могут возникнуть конфликты параллельной обработки данных (concurrency conflicts). Они обнаруживают себя тем, что возбуждают исключительные ситуации.

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

Однако рассмотрим другой сценарий. Вы вставляете новую строку данных, заполняете ее (кроме ячейки с первичным ключом—ее должен заполнить драйвер Access), нажимаете кнопку Save, затем удаляете эту же строку и вновь нажимаете Save. Проделайте это, и вы убедитесь, что возникнет исключение типа Concurrency violation, которое выбрасывает метод Update.

 Concurrency violation: the DeleteCommand affected 0 of the expected 1 records.

В сообщении говорится о том, что не удалось изменить ни одной записи. В некоторых книгах советуют после вызова метода Update, вызвать метод AcceptChanges для DataTable, или для DataSet.

daStud.Update(ds.Tables[0]);

ds.Tables[0].AcceptChanges();

Это действие лишнее, AcceptChanges автоматически вызывается в ходе выполнения Update. Причина исключения в том, что при удалении записи Access должен знать оригинальный первичный ключ (StudID), а то, что он получает от построителя, не всегда ему соответствует. Напомним, что поле StudID было автоматически сгенерировано драйвером Access.

Вообще же исключение Concurrency violation призвано защищать данные в процессе параллельной работы с ними нескольких пользователей. В разделе MSDN Introduction to Data Concurrency in ADO.NET описаны три разных подхода (стратегии) к организации поведения источника данных в подобных случаях.

·  Pessimistic Concurrency. В условиях повышенного спроса на данные таблицы дешевле рано установить блокировки на записи, чем восстанавливать их (roll back) после обнаружения конфликта. Поэтому активная (прочитанная) строка таблицы блокируется для всех пользователей до тех пор пока она не будет обновлена.

В условиях отсоединенного режима работы (то есть, в нашем случае) такой подход неприемлем. Мы прочли всю таблицу и отключились от базы. Записи реальной базы не заблокированы и могут изменяться другими пользователями. Стратегия Pessimistic Concurrency работала в предыдущей технологии — ADO.

·  Optimistic Concurrency. Именно этот подход использован в ADO.NET. Он заключается в том, что строка таблицы становится недоступной для других пользователей только в моменты ее обновления, во время выполнения команды Update. Попытки повторного изменения данных, то есть попытки изменить данные, которые уже были изменены (по сравнению с оригиналом), вызывают исключение типа Concurrency violation. Для того, чтобы корректно обработать эту ситуацию надо внести коррективы в алгоритм обновления.

·  Подход, именуемый Last in Wins (последний выигрывает). В рамках этого подхода запись также недоступна в моменты ее обновления, но проверка равенства полей старым значениям не производится и все данные обновляются, как того требует последовательность команд.

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

Убедитесь в том, что мы действительно получаем исключение типа Concurrency violation, вставляя новую строку, обновляя таблицу (Save), удаляя эту же запись и вновь нажимая Save. Обдумайте, как исправить ситуацию.

Отказаться от стратегии Optimistic Concurrency можно, работая с объектом класса AccessDataSource (в Web-приложениях). В этом случае команды DELETE и UPDATE будут значительно проще.