2012-05-02 1 views
4

Если пользователь # 1 удаляет запись в нашей базе данных Access 2007 (SQL Server ODBC Linked Tables), другие пользователи, вероятно, покажут # Удалено # в этой записи (в форме представления таблицы данных) , В некоторых случаях это может вызвать проблемы, потому что у меня есть код, который выполняется в текущем событии формы и просто предполагает, что существует действительная запись (или новая запись).Обнаружить, если текущая запись удалена по форме ограничения доступа

Есть ли надежный способ определить, была ли удалена текущая запись? Я хотел бы, чтобы обернуть его в функции, как это:

Public Function IsRecordDeleted(ByRef r As DAO.Recordset) 
    'what goes here? 
End Function 

Я нашел свойство RecordStatus в ссылке DAO в MSDN, но это свойство оказывается справедливым только если RecordSet сконфигурирован для пакетного обновления. Когда я пытаюсь проверить его значение, я получаю: Ошибка времени выполнения 3251. Операция не поддерживается для этого типа объекта.

Я фактически разместил на другом форуме эту же проблему год или два назад. Рекомендации, данные не работают:

  • DCOUNT()
  • Закладка и NoMatch из записей
  • Проверка #Deleted в ПК или поле FK
+0

Хороший вопрос, но я не думаю, что он будет работать с Requery в текущем событии. Это вызовет бесконечный цикл. Однако, если бы я обнаружил удаленную запись, это правда, что мне пришлось бы требовать разрешения проблемы, я думаю. – HK1

+0

@ HK1 Это может строго не помогать, но я всегда советую использовать сервер db в качестве исходного кода, чтобы избежать использования связанных связанных DAO связанных форм. Перейдите с помощью ADO для запуска любых запросов на стороне сервера, а не из локального, а также для кодирования несвязанного решения для формы. –

+0

Спасибо за рекомендацию. Я использую ADO как последнее средство. Если DAO и ODBC делают то, что мне нужно, я думаю, что я не вижу необходимости меняться. Но я понимаю, что ADO обычно считается более стабильным и надежным. – HK1

ответ

3

Для меня это больше похоже общий надзор за дизайном приложений, чем простая проблема, которая имеет простой обход.

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

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

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

  • Просто не полагаться на существование записей если вы не можете быть уверены, что они будут там.
    В принципе, переработайте свои предположения и измените свой существующий код, чтобы не полагаться на обязательное наличие записей.

  • Разделение ответственности
    Не допускайте, чтобы разные пользователи имели одинаковые права на создание/редактирование/удаление одних и тех же данных. Например, заказы на поставку должны принадлежать пользователю, который его создал. Не разрешайте другим пользователям удалять этот заказ или его элементы отдельно.

  • На самом деле не удаляйте объект, просто разрешите пользователю отмечать его как «Отмененный» или «Устаревший» и хранить его в базе данных по историческим причинам (или очистить их позже).

  • В качестве альтернативы, на самом деле не удалять записи, а добавлять скрытое логическое поле, чтобы пометить их как «удаленные», когда пользователь хочет их удалить. Затем вы можете выполнить некоторую очистку, сказать каждую ночь, и фактически удалить отмеченные записи.
    Конечно, вам придется исключать эти «удаленные» записи из ваших запросов и форм и т. Д., Но целостность данных будет сохранена.

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

  • Кэш-записи локально, так что, если они исчезнут из базы данных базы данных, они все равно будут отображаться для пользователя, просматривающего их, пока они не обновят список.
    Это часто полезно для отчетов только для чтения: загружает результат запроса в локальную таблицу и связывает эту таблицу вместо запроса с использованием живых данных.
    Просмотренные данные могут быть немного устаревшими, поскольку они не будут обновляться в режиме реального времени (поскольку они локализованы локально), но для отчетов это нормально (просто укажите кнопку «Обновить» в своей форме, чтобы пользователи могли принудительно обновить).

  • Экспериментируйте с различными вариантами блокировки (см. database options и form record locking), чтобы запретить удаление записей, если кто-то другой обращается к ним.

  • Управление собственной схемой блокировки.
    В качестве последнего средства вы можете записать в таблице «LockingStatus» идентификатор и записи, которые в настоящее время просматриваются или редактируются кем-то другим. Например:

    Table: LockStatus 
    Field: LockNature: Whether the record is being Edited or Viewed 
    Field: LockedTable: Name of the table of the record being locked 
    Field: LockedRecord: ID of the record being locked 
    Field: User:   Name of the user holding the lock 
    Field: LockTime:  DateTime of the lock creation, so you can detect 
            and remove stale locks 
    

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

  • Если вы все еще хотите обойти проблему с удаленной записью, посмотрите, где в вашем коде VBA ошибка 3167 «Запись удалена» возникает, когда вы удаляете запись из другого места.
    Как только вы узнаете, где это происходит в вашем коде, поймите эту ошибку с помощью On Error 3167 Goto YourErrHandler, чтобы обработать эту конкретную ошибку изящно (это будет действительно зависеть от того, как ваши формы создаются и как вы используете свои данные).

  • Другой альтернативой является использование глобального обработчика ошибок для доступа.
    Я знаю только vbWatchdog. Это не бесплатно, но работает очень хорошо и очень просто интегрироваться в приложение.
    Эта надстройка интегрируется в ваше приложение и не нуждается в установке отдельно для каждого пользователя. После настройки ваше приложение сможет уловить все ошибки на высоком уровне. Таким образом, вы сможете поймать ошибки «Record Deleted» и разобраться с ними в одном месте.

+0

Спасибо за ваш полный список решений и идей. Я не уверен, что согласен на 100% со всем, что вы написали, но я думаю, что ваш ответ хорошо справляется с этой проблемой. – HK1

0

Я столкнулся с тем же кодом с помощью кода в событии Form_Current и оказался здесь.

Обработка ошибок - лучший способ (и только?).Для моих собственных целей, я просто работаю несколько простых обновлений управления в текущем событии, и поэтому я написал, чтобы оправиться от ошибок обработчика ошибок я получает

Private Sub Form_Current() 
    On Error GoTo handler 

    'do intended things here, e.g. attempt to access the value 
    'of a control even though the record may be deleted 

    Exit Sub 

    handler: 
    If Err.Number = 438 Or Err.Number = 13 Then 
     'type mismatch, probably due to deleted record, skip it 
     Resume Next 
    ElseIf Err.Number = 3167 Then 
     'record is deleted, skip it 
     Resume Next 
    Else 
     Err.Raise Err.Number, Err.Source, Err.Description 
    End If 
End Sub 

Я не был надежно при получении 3167 (записи удалена), но при попытке доступа к свойствам ценности я, казалось, получал только 3 ошибки, захваченные выше.

Если ваше текущее событие длиннее или если это опасно для запуска такого кода, вы можете использовать подобный метод, но преднамеренно спровоцировать ошибку в начале метода (dummyvalue = SomeBoundControl.Value должен сделать трюк) и затем измените «Resume Next» в обработчике ошибок на «Exit Sub».

0

Вы можете проверить поле, которое соответствует , не заполнено обязательно, если запись все еще существует.

Я использую поле с обновленной датой или датой, которое автоматически заполняется значением по умолчанию = Now() после того, как форма открывается в первый раз.

Поскольку его значение, кажется, изменения в пустую строку, если запись была удалена, я могу вызвать

If Me.DateUpdated = "" Then 

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

Смежные вопросы