Упражнение 4.2: Обработка изменений на сервере
Задание 2 – Код для обработки изменений на сервере
В этом задании мы добавим новую внутреннюю процедуру во внешнюю процедуру dsPO_procs.p, которую мы создали на предыдущем практическом занятии. Эта новая процедура будет выполнять обновление базы данных на основе набора изменений и возвращать набор изменений назад клиенту.
Шаг | Действие |
1 | В OpenEdge Editor откройте процедуру dsPO_procs.p, которая была создана на предыдущем практическом занятии. |
2 | Опишите новую внутреннюю процедуру с именем update_dsPO, у которой есть один INPUT-OUTPUT параметр с именем phChangeDataSet и с атрибутом DATASET-HANDLE.
PROCEDURE update_dsPO: DEFINE INPUT-OUTPUT PARAMETER DATASET-HANDLE phChangeDataSet. RETURN. END PROCEDURE. |
3 | Опишите следующие переменные:
DEFINE VARIABLE hBuffer AS HANDLE NO-UNDO. DEFINE VARIABLE hBeforeBuffer AS HANDLE NO-UNDO. DEFINE VARIABLE hQuery AS HANDLE NO-UNDO. DEFINE VARIABLE iBufferCount AS INTEGER NO-UNDO. |
4 | Предположим, что в базе данных у таблицы POLine есть триггеры, которые срабатывают при внесении изменений в записи таблицы и корректируют соответствующую родительскую запись в таблице PurchaseOrder, например, общую сумму заказа. Нам необходимо отследить такие изменения в PurchaseOrder во время обработки изменений из набора изменений. Для этого мы сначала должны обработать записи таблицы ttPOLine, которые влияют на записи ttPurchaseOrder, а затем обработать изменения в записях ttPurchaseOrder. Это позволит последнему значению PurchaseOrder в базе данных попасть в ttPurchaseOrder, которая будет возвращена клиенту.
Первой таблицей в наборе данных является ttPurchaseOrder с ID 1, а вторая таблица это ttPOLine с ID 2. Таким образом прохождение по временным таблицам из набора изменений должно быть обратным. То есть, сначала обрабатываем записи из ttPOLine, а затем записи из ttPurchaseOrder. Чтобы это реализовать добавим следующий DO-блок в код нашей процедуры. DO iBufferCount = phChangeDataSet:NUM-BUFFERS TO 1 BY -1: END. |
5 | Внутри блока DO установим переменные hBuffer и hBeforeBuffer.
hBuffer = phChangeDataSet:GET-BUFFER-HANDLE(iBufferCount). hBeforeBuffer = hBuffer:BEFORE-BUFFER. |
6 | Добавим код проверки существования текущей таблицы BEFORE. Если существует, то добавляем ещё один блок DO. Если нет, то переходим к обработке следующей временной таблицы в наборе данных.
IF hBeforeBuffer <> ? THEN DO: END. |
7 | Внутри DO-блока, который подтверждает существование таблицы BEFORE, добавим код подключения источников данных.
IF hBuffer:NAME = "ttPurchaseOrder" THEN hBuffer:ATTACH-DATA-SOURCE(DATA-SOURCE srcPurchaseOrder:HANDLE). ELSE hBuffer:ATTACH-DATA-SOURCE(DATA-SOURCE srcPOLine:HANDLE). |
8 | Создадим динамический запрос и блок DO WHILE для цикла по всем записям таблицы BEFORE используя объект query до тех пор, пока не останется доступных записей.
CREATE QUERY hQuery. hQuery:ADD-BUFFER(hBeforeBuffer). hQuery:QUERY-PREPARE('FOR EACH ' + hBeforeBuffer:NAME). hQuery:QUERY-OPEN. hQuery:GET-FIRST. DO WHILE hBeforeBuffer:AVAILABLE: hQuery:GET-NEXT. END. |
9 | Если запись есть в таблице BEFORE, сохраним изменение в базе данных. Добавим следующий оператор в цикле DO WHILE перед оператором GET-NEXT.
hBeforeBuffer:SAVE-ROW-CHANGES(). |
10 | После оператора END блока DO для условия «IF hBeforeBuffer <> ?» добавьте оператор удаления объекта query и оператор отключения источника данных.
DELETE OBJECT hQuery. hBuffer:DETACH-DATA-SOURCE(). |
11 | Сохраните изменения в файле процедуры и убедитесь в отсутствии ошибок компиляции. |