Упражнение 6.1: Обработка системных ошибок
На этом практическом занятии вы напишите код для обработки ошибок набора данных, возникающих при отправке обновлений на сервер.
Сначала вы подготовите клиентский код для обработки атрибута ERROR, который автоматический устанавливается системой при неудачном вызове метода SAVE-ROW-CHANGES. Затем подготовите серверный код для установки атрибута REJECTED для строки и клиентский код для обработки отклонённой строки. В завершении подготовите серверный код для установки ERROR-STRING, когда приложение обнаружит ошибку, и клиентских код для получения значения ERROR-STRING.
Это занятие состоит из трёх заданий, на выполнение которых отводится примерно 45 минут.
Задание 1
В этом задании мы создадим процедуру обновления на сервере так, чтобы в случае ошибки при выполнении SAVE-ROW-CHANGES работа процедуры не была прервана. Это позволит системе установить атрибут ERROR для буфера временной таблицы, для временной таблицы и для набора данных, которые будут возвращены клиенту. Затем мы добавим код в тестовую процедуру для создания записей в таблице ttPurchaseOrder со значениями в поле PONum, которые не удастся добавить в базу данных на сервере. В клиентском коде вы исследуете атрибуты ERROR, когда вызов процедуры обновления вернётся с сервера, а затем исследуете содержимое набора данных когда набор данных изменений будет объединён с клиентским набором.
Шаг |
Действие |
1 | Сначала изменим серверный код. Откройте процедуру src/PurchaseOrder/dsPO_procs.p из проекта Server. |
2 | Скопируйте внутреннюю процедуру update_dsPO и переименуйте копию в update_dsPO_2. Далее эту процедуру мы изменим для поддержки обработки ошибок на сервере. |
3 | Внутри процедуры update_dsPO_2 добавьте NO-ERROR к вызову метода SAVE-ROW-CHANGES, чтобы процедура продолжила работать в случае возникновения ошибки.
Вызов метода SAVE-ROW-CHANGES теперь должен выглядеть так: hBeforeBuffer:SAVE-ROW-CHANGES() NO-ERROR. |
4 | Сохраните изменения. |
5 | Теперь изменим клиентский код. Откройте процедуру src/PurchaseOrder/access_dsPO_procs.p из проекта Client. |
6 | В код этой процедуры мы добавим обработку изменений в наборе данных. В начале процедуры опишите следующий переменные:
DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO. DEFINE VARIABLE hQuery AS HANDLE NO-UNDO. |
7 | В конце этой процедуры для данного тестового сценария добавьте комментарий о том, что далее вы будете тестировать автоматическую настройку системной ошибки.
Добавьте его перед комментарием «clean up» /*---------------------------------- Тестирование автоматической установки атрибута ERROR -----------------------------------*/ |
8 | Добавьте оператор очистки набора данных и откройте лог-файл с именем AutomaticErrorSetting_dsPO.log.
OUTPUT TO "C:\OpenEdge\WRK\ProDataSets\log\AutomaticErrorSetting_dsPO.log". DATASET dsPO:EMPTY-DATASET(). |
9 | Добавьте код для создания 3 новых записей ttPurchaseOrder. Установите значение PONum для каждой из этих записей равным 8001, 50000 и 8002, а также SupplierIDNum равным 5 для каждой записи.
Обратите внимание, что в базе данных уже есть записи PurchaseOrder для PONum 8001 и 8002, поэтому при отправке этого набора данных на сервер создание этих новых записей завершится ошибкой. /* включение отслеживания изменений */ TEMP-TABLE ttPurchaseOrder:TRACKING-CHANGES = TRUE. CREATE ttPurchaseOrder. ASSIGN ttPurchaseOrder.PONum = 8001 ttPurchaseOrder.SupplierIDNum = 5. CREATE ttPurchaseOrder. ASSIGN ttPurchaseOrder.PONum = 50000 ttPurchaseOrder.SupplierIDNum = 5. CREATE ttPurchaseOrder. ASSIGN ttPurchaseOrder.PONum = 8002 ttPurchaseOrder.SupplierIDNum = 5. /* отключение отслеживания изменений */ TEMP-TABLE ttPurchaseOrder:TRACKING-CHANGES = FALSE. |
10 | Создайте набор данных изменений из набора данных dsPO и отправьте его в код на стороне сервера с помощью процедуры update_dsPO_2.
CREATE DATASET hChangeDataSet. hChangeDataSet:CREATE-LIKE( DATASET dsPO:HANDLE). /* Обработка Get-Changes для получения изменений*/ hChangeDataSet:GET-CHANGES(DATASET dsPO:HANDLE). /* обновление данных на сервере */ RUN update_dsPO_2 IN hProc (INPUT-OUTPUT DATASET-HANDLE hChangeDataSet). |
11 | Добавьте код для обхода по набору изменений временной таблицы ttPurchaseOrder. Вы можете адаптировать код из процедуры update_dsPO2. Во время итерации определите строки, в которых установлен атрибут ERROR, и для этих строк запишите значение PONum в выходной файл.
Подсказка: чтобы получить доступ к значениям PONum созданных записей, вы должны использовать after-таблицу, а не before-таблицу. hBuffer = hChangeDataSet:GET-BUFFER-HANDLE("ttPurchaseOrder"). CREATE QUERY hQuery. hQuery:ADD-BUFFER(hBuffer). hQuery:QUERY-PREPARE('FOR EACH ' + hBuffer:NAME). hQuery:QUERY-OPEN. hQuery:GET-FIRST. DO WHILE hBuffer:AVAILABLE: IF hBuffer:ERROR THEN MESSAGE "PurchaseOrder " hBuffer::PONum " could not be added.". hQuery:GET-NEXT. END. DELETE OBJECT hQuery. |
12 | Добавьте код для объединения успешных изменений в наборе изменений обратно в набор данных dsPO, а затем удалите набор данных изменений.
hChangeDataSet:MERGE-CHANGES (DATASET dsPO:HANDLE). DELETE OBJECT hChangeDataset. |
13 | Добавьте код для итерации по набору данных dsPO и запишите PONum в выходной файл.
FOR EACH ttPurchaseOrder: MESSAGE "PurchaseOrder Number: " ttPurchaseOrder.PONum. END. |
14 | Закройте лог-файл.
OUTPUT CLOSE. |
15 | Сохраните эту процедуру, убедившись, что она компилируется без ошибок. |
16 | Поскольку вы изменили код на стороне сервера, перезапустите сервер приложений ProDataSets-Instance. Убедитесь, что сервер приложений перешёл в состояние «Started, Synchronized». |
17 | Выполните access_dsPO_procs.p для проверки ошибок, генерируемых системой.
Были ли у записей с PONum 8001 и 8002 задан атрибут ошибки? Содержит ли набор данных dsPO только одну запись после слияния? |