Иллюстрированный самоучитель по Microsoft Access 2002

Программная синхронизация доступа к данным

При одновременном доступе нескольких пользователей к одной и той же записи в источнике данных могут возникнуть конфликты. Например, конфликты могут возникать при выполнении метода Update или Delete объекта Recordset и метода OpenDatabase объекта Workspace или DBEngine. Предотвращение конфликтов зависит от настройки Access, касающейся методов блокировки записей, режима доступа к базе данных, периодов обновления данных. Об установке этих параметров мы уже говорили в разд. "Организация совместного доступа к данным и объектам" этой главы. Более подробную информацию можно найти в справочной системе Access.

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

Рассмотрим в качестве примера синхронизации функцию отправки сервером сообщения одному из игроков (программа 16.9). Вспомогательная функция doPause, позволяющая сделать паузу в работе приложения на заданное количество секунд, приведена в программе 16.10.

Программа 16.9. Синхронизация записи изменений в источнике данных

'Послать сообщение подключенному игроку
Public Sub SendMessage(message As String, playerName As String).
'Объявления локальных объектных переменных:
Dim db As Database
Dim rs As Recordset
Dim counter As Integer
'Определяем собственную обработку ошибок:
On Error GoTo errHandler
Set db = CurrentDb
'Открываем таблицу сообщений для игрока:
Set rs = db.OpenRecordset("Сообщения", dbOpenDynaset)
On Error GoTo 0
'Добавляем сообщение в таблицу сообщений клиента:
rs.AddNew
rs!ИмяИгрока = playerName
rs!Сообщение = message
'Обработка ошибок, возникающих при совместном доступе к источнику данных:
On Error GoTo tryAgain
rs.Update
On Error GoTo 0
rs.Bookmark = rs.LastModified
'Закрываем открытые объекты:
closeAHHandler:
    rs.Close
endHandler:
'Очищаем объектные переменные, т. к. они больше не используются:
Set rs = Nothing
Set db = Nothing
'Завершаем работу:
Exit Sub 
'Синхронизация: 
tryAgain:
counter = counter + 1 If counter < 400 Then
doPause 5 Resume
End If
Обработка ошибок: 
errHandler:
Dim errMsg As String
errMsg = "Ошибка: " & Err.Number & vbCrLf & "Источник: " & Err.Source & vbCrLf & vbCrLf & Err.Description
MsgBox errMsg, vbCritical, ERR_TITLE Resume endHandler
End Sub

Программа 16.10. Сделать паузу на заданное количество секунд в работе приложения

Public Sub doPause(seconds As Integer)
Dim var_timeStart, var_timeCurrent
Dim ftimeOut As Boolean
var_timeStart = Time()
'Время начала паузы Do
'Передать управление другим процессам операционной системы
DoEvents
var_timeCurrent = Time()
'Текущее системное время
ftimeOut = CDate(var timeCurrent - var timeStart) >= CDate(TimeSerial(0, 0, seconds))
Loop Until ftimeOut 
End Sub
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.