45805 (Перенос приложений MIDAS с одной СУБД на другую), страница 2
Описание файла
Документ из архива "Перенос приложений MIDAS с одной СУБД на другую", который расположен в категории "". Всё это находится в предмете "информатика" из , которые можно найти в файловом архиве . Не смотря на прямую связь этого архива с , его также можно найти и в других разделах. Архив можно найти в разделе "рефераты, доклады и презентации", в предмете "информатика, программирование" в общих файлах.
Онлайн просмотр документа "45805"
Текст 2 страницы из документа "45805"
Пример: предотвращение удаления клиента, если существуют документы с его участием (чтобы такой триггер не конфликтовал с ограничением ссылочной целостности, в MSSQL необходимо убрать foreign key с таблицы doc_title на client)
create trigger CLIENT_BEFORE_DELETE for CLIENT before delete as begin if (exists (select * from DOC_TITLE where FROM_ID = OLD.CLIENT_ID)) then exception EX_CLIENT_IN_DOC; if (exists (select * from DOC_TITLE where TO_ID = OLD.CLIENT_ID)) then exception EX_CLIENT_IN_DOC; end ^ |
Преобразуется в
create trigger CLIENT_AFTER_DELETE on CLIENT for delete as if (exists (select d.CLIENT_ID from DOC_TITLE dt, deleted d where dt.FROM_ID = d.CLIENT_ID)) begin --чтобы сообщение было видно на клиенте raiserror ('Существует запись в документе', 16, 1) --необходимо ручками откатить транзакцию rollback transaction end if (exists (select d.CLIENT_ID from DOC_TITLE dt, deleted d where dt.TO_ID = d.CLIENT_ID)) begin raiserror ('Существует запись в документе', 16, 1) rollback transaction end go |
Модификация сервера приложений.
Здесь основная часть переработки связана с переходом от IBX (InterBase Express) к ADO (ActiveX Data Object). Основные вещи, на которые следует обратить внимание:
Реализация транзакций на клиенте – в IBX это отдельный компонент, в ADO такая функциональность предоставляется методами TADOConnection. Еще небольшая рекомендация – аккуратно подходите к выбору уровня изоляции транзакций (чем меньше уровень изоляции, тем быстрее будет работать приложение).
Чтобы клиент работал без переделки с разными источниками данных, необходимо, чтобы типы данных полей совпадали. Например, в IBX для numeric(15, 4) по умолчанию подставляется TFloatField, а в ADO – TBCDField. Это единственное отличие, которое мне встретилось при переносе (но это не значит, что их вообще нет). Проблема решилась ручной установкой данного типа поля в TCurrencyField.
Перевод sql-выражений из синтаксиса IB в MSSQL.
Отличия, связанные с различиями структуры БД. Например, если будет реализовано каскадное удаление с помощью ХП, то придется реализовывать эту логику внутри сервера, чтобы оставить клиента нетронутым.
В качестве примера приведем перевод одной из процедур сервера приложений:
//Описание того, что делает данная процедура, читайте в статье Игнатьева. //Код, работающий с IBX function TrdmDoc.ApplyChanges: WideString; begin lock; try FLastUpdateErrors := ''; if FState = osInactive then raise Exception.Create('Документ не был создан либо открыт'); with cdsTitle do begin Edit; FieldByName('DOC_SUM').asCurrency := CalcSum; Post; end; ibtDoc.StartTransaction; //ibtDoc – компонент транзакции if FState = osInsert then begin if cdsTitle.ChangeCount > 0 then cdsTitle.ApplyUpdates(-1); if cdsBody.ChangeCount > 0 then cdsBody.ApplyUpdates(-1); end; if FState = osUpdate then begin if cdsBody.ChangeCount > 0 then cdsBody.ApplyUpdates(-1); if cdsTitle.ChangeCount > 0 then cdsTitle.ApplyUpdates(-1); end; Result := FLastUpdateErrors; if Result = '' then ibtDoc.Commit else begin ibtDoc.Rollback; end; finally ibtDoc.Active := False; //DefaultAction = Rollback unlock; end; end; //Код, работающий с ADO function TrdmDoc.ApplyChanges: WideString; begin lock; try FLastUpdateErrors := ''; if FState = osInactive then raise Exception.Create('Документ не был создан либо открыт'); with cdsTitle do begin Edit; FieldByName('DOC_SUM').asCurrency := CalcSum; Post; end; adcDocs.BeginTrans; //явные транзакции задаются на уровне соединения if FState = osInsert then //а не отдельным компонентом begin if cdsTitle.ChangeCount > 0 then cdsTitle.ApplyUpdates(-1); if cdsBody.ChangeCount > 0 then cdsBody.ApplyUpdates(-1); end; if FState = osUpdate then begin if cdsBody.ChangeCount > 0 then cdsBody.ApplyUpdates(-1); if cdsTitle.ChangeCount > 0 then cdsTitle.ApplyUpdates(-1); end; Result := FLastUpdateErrors; if Result = '' then adcDocs.CommitTrans else begin adcDocs.RollbackTrans; end; finally unlock; end; end; |
Заключение
Это всего лишь пример. В реальных приложениях следует более тщательно продумывать перенос приложений. Например, переписывать лучше не весь сервер приложений, а только зависимый от источника данных код, вынося его в отдельные модули.
Данная статья не претендует на полноту освещения данного вопроса, а также и автор при изложении подходов для решения проблем не претендует на роль "истины в последней инстанции". Здесь был изложен лишь минимум сведений, необходимый для решения поставленной задачи, а также некоторые размышления, которые могут помочь при решении схожих проблем.
Все вопросы, замечания, исправления, дополнения направляйте на kapusto@mail.ru
Хочу выразить признательность Игнатьеву Роману, Павлу Шмакову за советы, критику и настойчивость.
Список литературы
Для подготовки данной работы были использованы материалы с сайта http://www.rsdn.ru/