Упражнение 6.2: Установка и получение атрибута REJECTED
Задание 2
В этом задании вы создадите процедуру update_dsPO_3 на сервере так, что если приложение обнаружит ошибку (application constraint), то SAVE-ROW-CHANGES не вызывается, но атрибут REJECTED устанавливается для строки, а атрибут ERROR устанавливается для временной таблицы и набора изменений. Затем вы добавите код в процедуру тестирования для изменения записи ttPurchaseOrder, которая нарушает ограничение приложения (application constraint). В клиентском коде вы проверите атрибуты ERROR и REJECTED, когда процедура обновления вернётся с сервера, и увидите, что вызов MERGE-CHANGES откатит все изменения, отправленные клиентом на сервер и которые были отклонены.
Шаг |
Действие |
1 | В процедурном файле dsPO_procs.p скопируйте и вставьте процедуру update_dsPO_2, переименовав её в update_dsPO_3. Это процедура, которую вы измените для обработки ошибок на сервере. |
2 | Для вас была написана процедура ValidateData, текстовый файл который вы найдёте в каталоге ProDataSets\Exercise\Lesson06. Откройте этот файл в текстовом редакторе и скопируйте его содержимое в конец процедурного файла dsPO_procs.p. |
3 | Изучите процедуру ValidateData. Он принимает динамически изменяемый набор данных в качестве параметра ввода-вывода. Процедура проходит через все записи ttPurchaseOrder и, если какая-либо из них имеет значение SupplierIDNum больше 10, запись помечается как отклоненная. Затем она перебирает записи ttPOLine и также отклоняет все связанные записи ttPOLine. Эта процедура проверки данных будет вызвана во время обновления. |
4 | В процедуре update_dsPO_3 добавьте оператор, который будет выполнять процедуру ValidateData перед началом итерации для временных таблиц в наборе данных изменений.
Добавьте этот код сразу после описания переменных: /* выполните процедуру для пометки записей с ошибками как отклоненных */ RUN ValidateData(INPUT-OUTPUT DATASET-HANDLE phChangeDataSet). |
5 | В процедуре update_dsPO_3 добавьте код к итерации, чтобы SAVE-ROW-CHANGES вызывался только в том случае, если hBeforeBuffer:ERROR имеет значение false.
В противном случае атрибут ERROR набора данных изменений устанавливается в значение true, также как для временной таблицы hBeforeBuffer. Замените вызов SAVE-ROW-CHANGES следующим кодом: IF NOT hBeforeBuffer:REJECTED THEN hBeforeBuffer:SAVE-ROW-CHANGES() NO-ERROR. ELSE DO: phChangeDataset:GET-BUFFER-HANDLE(iBufferCount):TABLE-HANDLE:ERROR= TRUE. phChangeDataset:ERROR = TRUE. END. |
6 | Сохраните эту процедуру, убедившись, что она компилируется без ошибок. |
7 | Далее вы добавите код в клиентскую тестовую процедуру access_dsPO_procs.p. Откройте её файл. |
8 | Добавьте комментарий к концу этой процедуры для данного тестового сценария, в котором вы будете тестировать автоматическую настройку системной ошибки.
Добавьте его перед комментарием «clean up» /*---------------------------------- Тестирование отклонения записей с установкой атрибутов REJECTED и ERROR -------------------*/ |
9 | Добавьте оператор очистки набора данных и откройте лог-файл с именем RejectingRecords_dsPO.log.
OUTPUT TO "C:\OpenEdge\WRK\ProDataSets\log\RejectingRecords_dsPO.log". DATASET dsPO:EMPTY-DATASET(). |
10 | Добавьте код для включения отслеживания изменений для обеих временных таблиц набора данных dsPO.
/* включение отслеживания изменений */ TEMP-TABLE ttPurchaseOrder:TRACKING-CHANGES = TRUE. TEMP-TABLE ttPOLine:TRACKING-CHANGES = TRUE. |
11 | Добавьте код для:
Добавьте этот код в процедуру: /* Создание записи PurchaseOrder c действительным ID поставщика ( < = 10) */ CREATE ttPurchaseOrder. ASSIGN ttPurchaseOrder.PONum = 60000 ttPurchaseOrder.SupplierIDNum = 10. CREATE ttPOLine. ASSIGN ttPOLine.Linenum = 1 ttPOLine.PONum = 60000 ttPOLine.ItemNum = 5 ttPOLine.Price = 10 ttPOLine.Qty = 10 ttPOLine.Discount = 0 ttPOLine.ExtendedPrice = 100. ttPurchaseOrder.POTotal = ttPurchaseOrder.POTotal + 100. CREATE ttPOLine. ASSIGN ttPOLine.Linenum = 2 ttPOLine.PONum = 60000 ttPOLine.ItemNum = 10 ttPOLine.Price = 10 ttPOLine.Qty = 10 ttPOLine.Discount = 0 ttPOLine.ExtendedPrice = 100. ttPurchaseOrder.POTotal = ttPurchaseOrder.POTotal + 100. /* Создание второй записи PurchaseOrder c не действительным ID поставщика ID ( > 10) */ CREATE ttPurchaseOrder. ASSIGN ttPurchaseOrder.PONum = 60001 ttPurchaseOrder.SupplierIDNum = 11. CREATE ttPOLine. ASSIGN ttPOLine.Linenum = 1 ttPOLine.PONum = 60001 ttPOLine.ItemNum = 5 ttPOLine.Price = 10 ttPOLine.Qty = 10 ttPOLine.Discount = 0 ttPOLine.ExtendedPrice = 100. ttPurchaseOrder.POTotal = ttPurchaseOrder.POTotal + 100. CREATE ttPOLine. ASSIGN ttPOLine.Linenum = 2 ttPOLine.PONum = 60001 ttPOLine.ItemNum = 10 ttPOLine.Price = 10 ttPOLine.Qty = 10 ttPOLine.Discount = 0 ttPOLine.ExtendedPrice = 100. ttPurchaseOrder.POTotal = ttPurchaseOrder.POTotal + 100. |
12 | Добавьте код для отключения отслеживания изменений.
/* отключение отслеживания изменений */ TEMP-TABLE ttPurchaseOrder:TRACKING-CHANGES = FALSE. TEMP-TABLE ttPOLine:TRACKING-CHANGES = FALSE. |
13 | Добавьте код для создания набора данных изменений и выполнения процедуры update_dsPO_3.
/* Создание набора изменений с именем hChangeDataSet */ /* с такой же структурой как у dsPO */ CREATE DATASET hChangeDataSet. hChangeDataSet:CREATE-LIKE( DATASET dsPO:HANDLE). /* Обработка Get-Changes для извлечения изменений на уровне ProDataSet */ hChangeDataSet:GET-CHANGES(DATASET dsPO:HANDLE). /* обновление данных на сервере */ RUN update_dsPO_3 IN hProc (INPUT-OUTPUT DATASET-HANDLE hChangeDataSet). |
14 | Добавьте код для итерации по возвращённому набору данных изменений и записи сведений об атрибутах ERROR, а также о том, были ли строки отклонены.
/* цикл по всем записям во временной таблице ttPurchaseOrder и отображение информации об ошибка и отвергнутых строках */ MESSAGE "Change dataset ERROR attribute is: " hChangeDataset:ERROR. /* проходим по записям ttPurchaseOrder */ hBuffer = hChangeDataSet:GET-BUFFER-HANDLE("ttPurchaseOrder"). MESSAGE "ttPurchaseOrder ERROR attribute is: " hChangeDataSEt:GET-BUFFER-HANDLE("ttPurchaseOrder"):TABLE-HANDLE:ERROR. 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:REJECTED THEN MESSAGE "PurchaseOrder " hBuffer::PONum " was rejected.". hQuery:GET-NEXT. END. DELETE OBJECT hQuery. /* проходим по записям ttPOLine */ hBuffer = hChangeDataSet:GET-BUFFER-HANDLE("ttPOLine"). MESSAGE "ttPOLine ERROR attribute is: " hChangeDataSet:GET-BUFFER-HANDLE("ttPOLine"):TABLE-HANDLE:ERROR. 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:REJECTED THEN MESSAGE "POLine " hBuffer::PONum "Line " hBuffer::LineNum " was rejected.". hQuery:GET-NEXT. END. DELETE OBJECT hQuery. |
15 | Добавьте код для слияния набора данных изменений обратно в набор данных клиента, а затем удалите набор данных изменений.
hChangeDataSet:MERGE-CHANGES (DATASET dsPO:HANDLE). DELETE OBJECT hChangeDataset. |
16 | Добавьте код для итерации по всем записям во временной таблице после слияния и отображения некоторых значений. Затем закройте выходной файл.
MESSAGE "***********After updates are merged: ". FOR EACH ttPurchaseOrder NO-LOCK: MESSAGE "PurchaseOrder Number: " ttPurchaseOrder.PONum "Supplier ID: " ttPurchaseOrder.SupplierIDNum. FOR EACH ttPOLine OF ttPurchaseOrder NO-LOCK: MESSAGE "POLine: " ttPOLine.Linenum. END. END. OUTPUT CLOSE. |
17 | Сохраните эту процедуру, убедившись, что она компилируется без ошибок. |
18 | Поскольку вы изменили код на стороне сервера, перезапустите сервер приложений ProDataSets-Instance. Убедитесь, что сервер приложений перешёл в состояние «Started, Synchronized». |
19 | Выполните access_dsPO_proces.p. Проверьте выходной файл. Были ли записи отклонены и правильно ли установлены атрибуты ошибок? После слияния на клиенте существует ли единственный набор записей для заказа на покупку с идентификатором поставщика меньше или равен 10?
В файле должно быть следующее: Change dataset ERROR attribute is: yes ttPurchaseOrder ERROR attribute is: yes PurchaseOrder 60001 was rejected. ttPOLine ERROR attribute is: yes POLine 60001 Line 1 was rejected. POLine 60001 Line 2 was rejected. ***********After updates are merged: PurchaseOrder Number: 60000 Supplier ID: 10 POLine: 1 POLine: 2 |