Перенос приложений cbuilder в архитектуру клиентсервер


Содержание

Клиент-серверное приложение

28.11.2020, 20:12

Клиент-серверное приложение
С помощью каких компонентов или функций можно разработать клиент-серверное приложение?

Клиент серверное приложение не работает
клиент void __fastcall TForm1::ClientSocket1Connect(TObject *Sender, TCustomWinSocket *Socket).

Клиент-серверное приложение средствами IPC
Всем доброго времени суток. Нужно написать 2 приложения: Клиент и Сервер Клиент должен используя.

Клиент-серверное приложение. Одновременный запрос клиентов
Приложения нормально работают с одним клиентом при не слишком частых запросах (интервал между.

Клиент-серверное приложение, сохранение переписки в файл
Здраствуйте!):) У меня есть два приложения: одно-клиентская часть, второе-серверная часть. Передача.

Лекция 1. Введение в архитектуру клиент-серверных андроид-приложений. Часть 1

Представляем курс по архитектуре клиент-серверных андроид-приложений на основе материалов курса Артура Василова, который проходил на Google Developers Group 2020 в Казани.

Чтобы на практике познакомиться с архитектурой клиент-серверных приложений, записывайтесь на продвинутый курс по разработке приложения «Чат-мессенжер»

Введение в архитектуру android приложений

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

И этот вопрос логичен. Во-первых, пользователю совсем-совсем безразлична архитектура вашего приложения. Серьезно, кто из вас при использовании программ и приложений часто задумывается о том, сделали его по MVP или MVC? Ответ – никто. Во-вторых, работа с архитектурой требует дополнительных усилий: ее нужно создавать, в нее нужно вникать и учить людей работать по ней. Но чтобы создать более четкую картину для ответа на этот вопрос, нужно вернуться в относительно недалекое прошлое, а именно в 2007 и 2008 года, когда были выпущены соответственно первые версии устройств под iOS и Android.

Нужно признать, что Google успел отстать от Apple в плане выхода на мобильный рынок и это привело к некоторым последствиям, а именно к спешке при выходе первой версии Android. Нет ничего удивительного в том, что Google стремился в первую очередь доделать основные пользовательские функции, а забота об удобстве разработчиков была вторым приоритетом. Поэтому вместе с первой версией Android Google не предоставил разработчикам каких-то стандартных рекомендаций ни по разработке, ни по дизайну и UX. Что привело к тому, что каждый разработчик или каждая компания были вынуждены писать как хотели и как умели.

Конечно, нужно признать, что в дальнейшем Google проделал огромную работу по популяризации системы Android среди разработчиков. Но при этом изначальные проблемы так и не были до конца решены.

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

  • Невозможно поддерживать. В коде будет много сложной логики, она не будет расположена в строго определенных классах, будет непонятно, как работает та или иная часть вашего приложения. Из этого следует, что при добавлении нового функционала вам придется либо долго и усиленно разбираться в написанном коде, рефакторить его и делать все правильно, либо сделать задачу кое-как, то есть, образно говоря, через костыли. В связи с тем, что не все разработчики понимают необходимость рефакторинга и умеют убеждать в этой необходимости руководство, и не каждый руководитель согласится отсрочить выход новой версии и понести дополнительные траты из-за рефакторинга, намного чаще выбирается второй вариант. Это часто приводит к ужасающим последствиям. Лично мне не раз приходилось видеть огромные приложения, состоящие из трех файлов Activity. Разумеется, каждая из этих Activity состояла из тысяч, а то и из десятков тысяч строк, что делало их абсолютно невозможными для чтения. Более того, каждый новый функционал, реализованный через костыли, является причиной дополнительных багов и крашей.
  • Невозможно протестировать. Эта проблема плавно вытекает из первой. Вы не сможете писать модульные тесты, если все приложение – это один большой модуль. Более того, в силу особенностей написания тестов для Android-приложений на JVM, при большом количестве зависимостей от классов Android в тестируемых классах, вы не сможете писать тесты. А отсуствие тестов:
    1. Дает вам гораздо меньше уверенности в том, что ваш код работает правильно.
    2. Вы не сможете быстро проверить, что добавленные изменения не сломают работу остальных частей вашего приложения.

Такая ситуация продолжалась достаточно долго. Приложения под Android продолжались писаться в разных стилях с абсолютно разными подходами в дизайне и в архитектуре. Кто-то брал дизайн из системы iOS, а паттерны проектирования из Web-разработки (в частности, попытки использовать MVC в Android обязаны своему существованию именно Web-разработчикам, перешедшим в Android). И сложно сказать, почему не было никаких попыток исправить эту ситуацию, Android – это очень молодая система, и к моменту ее выхода все паттерны проектирования и архитектурные паттерны уже были широко известны.

В общем, все шло своим чередом до 2014 года, когда случилось сразу два важнейших события. Первое хорошо известно всем – это презентация концепции Material Design на Google I/O. Можно по-разному относиться к этой концепции, кто-то считает ее неудачной, кто-то говорит, что таким образом Google ограничивает свободу разработчиков в выборе дизайна. Но то, что появление этой концепции сильно улучшило ситуацию в среднем, – это бесспорно.

Понятно, что за конференцией Google I/O следят все и что Google приложил немало усилий в популяризации философии Material Design, так что Material Design был обречен на использование всеми. А вот другое знаковое событие произошло куда с меньшей популярностью, так как это была всего лишь статья. Это статья “Architecting Android… The clean way?” от Fernando Cejas. По сути эти всего лишь адаптация принципов Clean Architecture от “дядюшки Боба” (Роберта Мартина) для использования в Android. Эта статья дала огромный толчок (а вполне возможно, что это просто совпадение и статья вышла в тот момент, когда разработчики уже были готовы искать лучшие решения) в развитии архитектуры приложений.

Если говорить кратко (а подробнее мы посмотрим дальше по курсу), то хорошая архитектура должна позволять писать тесты для классов, содержащих бизнес-логику и должна строить модули приложения независимыми от почти всех внешних элементов. А если говорить еще проще, то ваш код должен быть тестируемым и его должно быть легко применять и приятно читать. Качество кода приложения можно даже замерить стандартной единицей измерения – количество WTF в минуту (из книги Роберта Мартина “Clean Code”).

Теперь мы можем примерно представить, что от нас требуется при построении архитектуры приложения и можем перейти непосредственно к рассмотрению всех тем!

Основные задачи при разработке клиент-серверных приложений

Так в чем же заключается сложность создания клиент-серверных Android-приложений, которые бы удовлетворяли всем принципам, которые были описаны ранее? Есть 2 крупные проблемы, каждую из которых на самом деле можно разбить еще на большее число проблем:

  • Реализация клиент-серверного взаимодействия. Казалось бы, в чем здесь проблема? Мы все умеем выполнять запросы к серверу с использованием различных средств, обрабатывать результат и показывать его пользователю. И да, и нет. Здесь существует масса факторов. Во-первых, нужно уметь корректно обрабатывать ошибки, которые могут быть самыми разными: от отсутствия интернета и неправильных параметров в запросе, до не отвечающего сервера и ошибках в ответе. Во-вторых, в вашем приложении может быть не один запрос, а много, и вполне возможна ситуация, что вам придется комбинировать результаты этих запросов сложным образом: выполнять их параллельно, использовать результат предыдущего запроса для выполнения следующего и так далее. В-третьих, и это самое неприятное – запросы могут занимать значительное время, а пользователь часто не самый терпеливый и тихий человек – он может крутить устройство (и тогда вы потеряете текущие данные в Activity), а может и вовсе закрыть приложение, и тогда вы можете получить рассинхронизацию в данных (когда на сервере данные обновились, а приложение не знает об этом и отображает некорректную или устаревшую информацию). И все это нужно каким-то образом решать.
  • Обеспечение возможности тестирования классов, содержащих бизнес-логику приложения. Это также подразумевает под собой немало внутренних проблем. Во-первых, нужно обеспечить модульность классов. Это следует из самой сути и из самого названия Unit-тестов. Чтобы обеспечить модульность, нужно разделять классы по логическим слоям для каждого экрана. То есть вместо того, чтобы писать весь код, относящийся к одному экрану, в одной активити, нужно грамотно разделить его на несколько классов, каждый из которых будет иметь свою зону ответственности. Во-вторых, если говорить о тестах с помощью JUnit, то нужно понимать, что тестируемые таким образом классы должны содержать минимальное количество зависимостей от Android-классов, так как Java и ее виртуальная машина об этих классах не знает ничего (подробнее этот момент будет описан в лекции про тестирование). В-третьих, самая сложная логика приложения почти всегда связана с работой с данными от сервера. Мы должны протестировать различные возможные ситуации, такие как ожидаемый ответ сервера, ошибка сервера и разные ответы, приводящие к разному поведению приложения. Но при выполнении теста мы не можем по своему желанию “уронить” сервер или заставить его отдать нужные нам данные. К тому же, серверные запросы выполняются долго и асинхронно, а тесты должны работать последовательно. Все эти проблемы можно решить, если подменять реализацию сервера на определенном слое, к которому будут обращаться тестируемые классы. Все это также будет рассмотрено далее.

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

Перенос приложений cbuilder в архитектуру клиент/сервер

Одним из главных факторов, влияющих на принятие решения о переносе информационных систем в архитектуру клиент/сервер, является потенциальная возможность повышения производительности работы пользователей, особенно в тех случаях, когда находящиеся в эксплуатации приложения не удовлетворяют требованиям, предъявляемым к скорости обработки данных ввиду их большого объема, а также высокой интенсивности и сложности запросов. Известно, что информационные системы, основанные на архитектуре клиент/сервер, могут обладать существенными преимуществами перед информационными системами, базирующимися на сетевых версиях настольных СУБД, такими, как существенно меньший сетевой трафик, меньшее время обработки запросов, меньшая ресурсоемкость клиентских приложений и меньшие трудозатраты при их разработке.

Однако сам по себе факт переноса имеющейся базы данных из настольной СУБД на какой-либо сервер баз данных с соответствующей корректировкой настроек BDE (или других средств доступа к данным) отнюдь не гарантирует повышения производительности информационной системы в целом. Представьте себе, например, базу данных, содержащую одну-единственную таблицу из сотни записей и пяти целочисленных полей, содержащуюся в Oracle Workgroup Server, функционирующем под управлением Windows NT на персональном компьютере с 16 Мб оперативной памяти, и однопользовательское приложение, использующее навигационные методы для ее редактирования. В этом случае, безусловно, проще хранить данные в таблице формата dBase или Paradox — производительность системы будет в этом случае, скорее всего, намного выше, так как такой сервер, как Oracle, требует сам по себе немало ресурсов, а объем обрабатываемых данных и технология их обработки не оправдывают затрат, связанных с приобретением, установкой и эксплуатацией серверной СУБД такого класса. Данный пример, конечно, несколько утрирует реальную ситуацию, но иногда на практике происходят и более экзотические случаи…

Итак, какие шаги нужно предпринять для того, чтобы действительно повысить эффективность работы пользователей и производительность системы в целом? Первым шагом в данном направлении является, конечно, выбор сервера. В этом случае, к сожалению, нельзя давать однозначных рекомендаций типа «возьмите Oracle, он надежен» или «возьмите IB, он недорого стоит». Выбор сервера, управляющей им операционной системы и соответствующего аппаратного обеспечения должен осуществляться с учетом реальных и потенциально ожидаемых условий эксплуатации системы, таких, как скорость роста объема данных (например, в мегабайтах в месяц), интенсивность транзакций, вероятность многопользовательского доступа к одной или соседним записям в таблицах (при высокой вероятности желательно выбрать сервер, при использовании которого можно избежать страничных блокировок), потенциальный рост интенсивности работы пользователей, наличие повышенных требований к безопасности и защите данных (некоторые серверные СУБД выпускаются в разных исполнениях, отличающихся друг от друга степенью защищенности данных), необходимость использования продуктов сторонних производителей (таких, как ODBC-драйверы, дополнительные библиотеки и утилиты и др.), наличие связанных с этим проблем (типичным примером из недавней реальной практики была, например, проблема поиска ODBC-драйвера к серверу Centura SQLBase 6.0, поддерживающего использование хранимых процедур). Не менее, чем технические, важны и финансовые аспекты этой проблемы. Планируется ли использовать для установки серверной СУБД уже имеющеся вычислительные мощности и операционную систему или следует приобрести новые? В какую сумму обойдется приобретение серверной СУБД, клиентских лицензий, аппаратного обеспечения? Сколько будет стоить администрирование этой СУБД и управляющей ей операционной системы, а также обучение будущих администраторов и программистов? Сколько подключений к серверу допускается при приобретении одной лицензии — одно, два, четыре? Каковы условия, налагаемые лицензионными соглашениями при использовании мультиплексирования соединений за счет эксплуатации серверов приложений, если в дальнейшем возможен переход к трехзвенной архитектуре? Принятие решения о выборе серверной СУБД существенно зависит от ответа на все эти вопросы, и не всегда технические аспекты или мнение разработчиков определяют в конечном итоге выбор сервера. Нередки также случаи, когда предполагается использование уже имеющейся в наличии серверной СУБД (или даже готовой базы данных).

Предположим, что сервер выбран (исходя из вышеизложенных или каких-либо иных соображений). Каким образом следует использовать предоставляемые им возможности? Эффективность эксплуатации информационной системы с точки зрения производительности зависит от согласованной работы трех ее составных частей — сервера баз данных, клиентского приложения и клиентской части серверной СУБД, функционирующих на рабочей станции, и сети, и неоптимальная работа одной из этих частей может свести к нулю результат всех усилий, направленных на оптимизацию работы остальных частей. Таким образом, проблема оптимизации работы информационной системы достигается путем решения нескольких задач: оптимизации клиентской части, оптимизации серверной части, снижения сетевого трафика. Ниже мы рассмотрим некоторые приемы, способствующие в той или иной степени решению этих задач. Однако перед этим изучим один из простейших способов контроля содержимого запросов, пересылаемых на сервер баз данных библиотекой BDE, и результатов их выполнения, с помощью утилиты SQL Monitor, входящей в комплект поставки С++Builder.

Контроль запросов с помощью SQL Monitor.

SQL Monitor используется для контроля запросов, пересылаемых клиентским приложением серверу баз данных посредством BDE, и их результатов, а также измерения времени между ними. Для его запуска следует выбрать пункт SQL Monitor из меню Database C++Builder. Главное окно SQL Monitor состоит из двух частей. В верхней части отображаются последовательно генерируемые SQL-предложения и сведения об откликах сервера, а также порядковый номер и время их наступления, а в нижней части — полный текст SQL-запроса. Список, отображаемый в верхнем окне, можно сохранить в файле для дальнейшего анализа. На рис.1 представлен типичный вывод сведений при работе приложения, рассмотренного в предыдущей статье данного цикла.

Рис.1. Вывод сведений о выполнении сервером запросов в SQL Monitor

При использовании SQL Monitor возможен выбор типов отображаемых сведений. Их можно выбрать в диалоге Trace Options, вызываемом из меню Options.

Рис.2. Диалог Trace Options для выбора действий, отображаемых в SQL Monitor

SQL Monitor позволяет отображать сведения о следующих действиях:

  • Prepared Query Statements — SQL-предложения, передаваемые на сервер
  • Executed Query Statements — SQL-предложения, готовые к выполнению сервером
  • Statement Operations — действия, выполняемые сервером (FETCH, EXECUTE и др.)
  • Connect/Disconnect — действия, связанные с установкой или разрывом соединения с сервером.
  • Transactions — действия, связанные с выполнением транзакций (BEGIN, COMMIT, ROLLBACK)
  • Blob I/O — действия, связанные с передачей Blob-полей
  • Miscellaneous — другие действия
  • Vendor Errors — сообщения об ошибках, возвращаемые сервером
  • Vendor Calls — вызовы функций API клиентской части, связанных с обращением к серверу

Использование SQL Monitor является простейшим (хотя и не единственным) средством тестирования производительности информационных систем в архитектуре клиент/сервер, и эффективность применения большинства рассматриваемых ниже приемов их оптимизации можно проконтролировать с его помощью.

Минимизация обращений к серверу и сети

Минимизация связей с сервером влияет на производительность всех составных частей информационной системы — клиента, сервера и сети. Лишние связи с сервером приводят к созданию дополнительных объектов (таких, как TDatabase) в клиентском приложении, генерации дополнительных запросов к серверу для выяснения прав пользователя на доступ к тем или иным объектам базы данных, а также к непроизводительному использованию ресурсов сервера. Для минимизации связей с сервером можно использовать такие приемы, как использование в явном виде компонента TDatabase вместо неявного их создания, использование кэширования данных и структуры, хранение сведений о метаданных в клиентском приложении, использование локальных фильтров и др.

Использование компонента TDatabase

При использовании нескольких компонентов TDataSet следует иметь в виду, что каждый из них стремится во время выполнения создать неявно свой объект TDatabase для связи с сервером. Если же поместить компонент TDatabase на форму или в модуль данных на этапе проектирования приложения, и связать с ним все компоненты TDataSet, указав его имя в качестве значения свойства DatabaseName этих компонентов, все они будут использовать одну общую связь, обеспеченную этим компонентом.

Использование параметра SQLPASSTHRU MODE

Еще один способ минимизации связей с сервером заключается в изменении значения параметра SQLPASSTHRU MODE компонента TDatabase (либо псевдонима, созданного утилитой конфигурации BDE). Этот параметр определяет, могут ли использоваться общие соединения с базой данных запросами, сгенерированными приложением (например, с помощью компонента TQuery), и запросами, сгенерированными самой библиотекой BDE (например, при реализации навигационных методов компонента TTable). Значением этого параметра по умолчанию является NOT SHARED, позволяющее избежать возможных конфликтов при многопользовательском обновлении данных, но создающее отдельные соединения с базой данных для обоих типов запросов.

Наиболее эффективным с точки зрения минимизации соединений с базой данных значением этого параметра в большинстве случаев является значение SHARED AUTOCOMMIT. При использовании этого значения изменения каждой записи в таблицах немедленно фиксируются сервером независимо от типа вызвавшего их запроса, но при этом оба типа запросов могут использовать одно и то же соединение с базой данных. Этот режим наиболее близок к режиму, в котором используются сетевые версии настольных СУБД. Однако так как сервер в этом случае должен немедленно фиксировать результаты изменения записей, он инициирует и завершает отдельную транзакцию при изменении каждой записи, что может привести к перегрузке сервера и сети и к снижению производительности вместо ожидаемого ее повышения. Поэтому эффективность использования такого режима должна быть обязательно проверена путем тестирования.

Третье возможное значение этого параметра — SHARED NOAUTOCOMMIT. В этом случае оба типа запросов могут также использовать одно и то же соединение с базой данных, причем без завершения транзакций после редактирования каждой записи. Однако в этом случае контроль за завершением транзакций следует осуществлять в клиентском приложении. Подобный режим может быть весьма эффективен, так как перегружающие сервер транзакции автоматически не инициируются после редактирования каждой записи, но при его использовании могут возникать конфликты и непредсказуемые изменения данных при попытке одновременного редактирования одной и той же записи разными пользователями. Поэтому данный режим следует использовать только в том случае, если вероятность подобных коллизий мала.

Кэширование метаданных на рабочей станции

Еще один способ минимизации связей с сервером заключается в использовании кэширования структуры таблиц на рабочей станции. В этом случае снижается число обращений к серверу с целью определения метаданных, т.е. количества столбцов в используемых в приложении таблицах, их имен и типов данных. Для этой цели используются следующие параметры псевдонима базы данных (или компонента TDatabase):
ENABLE SCHEMA CACHE — разрешено ли кэширование метаданных;
SCHEMA CACHE SIZE — количество таблиц, структура которых кэшируется;
SCHEMA CACHE TIME — время хранения информации в кэше в секундах; значение -1 соответствует времени хранения данных в кэше до закрытия приложения;
SCHEMA CACHE DIR — каталог для кэширования метаданных.

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

Использование потомков TField в клиентском приложении

Другим способом хранения на рабочей станции приложении сведений о метаданных является использование компонентов — потомков TField. Так как соответствующие объекты хранят сведения о структуре таблиц непосредственно в приложении, на этапе выполнения не производится обращений на сервер с целью получения метаданных. Использование потомков TField предпочтительнее, чем использование методов FieldByName() или свойства Fields, так как последние используют обращение к серверу для получения сведений о типах полей. Ограничения на применение компонентов — потомков TField такие же, как и в предыдущем случае — их использование рекомендуется при стабильной структуре таблиц. Помимо этого, изменение структуры данных на сервере может потребовать модификации приложения и, как следствие, установку его новой версии на рабочие станции.

Кэширование данных на рабочей станции

Помимо кэширования метаданных нередко применяется и кэширование на рабочей станции самих данных. Для этой цели следует установить равным true значение свойства CachedUpdates соответствующего компонента TDataSet. В этом случае все внесенные пользователем изменения сохраняются в локальном кэше. Сохранение данных на сервере производится с помощью метода ApplyUpdates() компонента TDataSet, а метод CommitUpdates() очищает кэш. В целом такой метод снижает сетевой трафик и суммарное число соединений с сервером, так как, во-первых, при редактировании данных в кэше не требуется наличия соединения с сервером, а во-вторых, сохранение нескольких записей из кэша на сервере может быть осуществлено путем выполнения одной-единственной транзакции. Помимо этого, снижается суммарное число блокировок записей на сервере, так как в процессе редактирования данных в кэше необходимости в блокировках нет.

Использование локальных фильтров при небольших объемах данных

Если компонент TDataSet доставляет на рабочую станцию небольшой по объему набор данных, сравнимый с размером кэша рабочей станции (определяемого параметрами MINBUFSIZE и MAXBUFSIZE системных настроек BDE), он будет полностью кэшироваться на рабочей станции. В этом случае применение локальных фильтров более предпочтительно, чем использование запросов с предложением WHERE, направляемых на сервер, так как в первом случае не требуется обращение к серверу.

Оптимизация использования сервера

Использование хранимых процедур

При выполнении многократно повторяющихся действий, использующих данные с сервера (например, при статистической обработке содержащихся в таблицах данных) производительность информационной системы можно повысить, используя хранимые процедуры сервера вместо SQL-запросов, генерируемых клиентским приложением. Дело в том, что переданный из клиентского приложения SQL-запрос сервером оптимизируется, компилируется и лишь затем выполняется, а хранимые процедуры сервера уже содержатся в оптимизированном и скомпилированном виде, поэтому обработка данных с их использованием требует меньших затрат времени, особенно при небольшом числе и суммарном объеме передаваемых параметров процедуры.

Однако следует иметь в виду, что хранимые процедуры пишутся на процедурном расширении SQL используемого сервера. Cуществуют официальные стандарты непроцедурного языка SQL ANSI/ISO SQL-86, SQL-89 и SQL-92, но на сегодняшний день не существует стандартов на процедурные расширения этого языка. Каждая серверная СУБД имеет свой набор процедурных расширений, отличающийся от соответствующих расширений других СУБД. Некоторые сервера, например Borland IB Database, поддерживают создание и использование в процедурах функций, определенных пользователем (UDF — User Defined Functions), а некоторые не поддерживают. Поэтому при смене платформы хранимые процедуры, скорее всего, потребуется переписывать. Отметим также, что чаще всего серверные хранимые процедуры создаются путем ручного кодирования, и для их создания, как правило, не существует удобных визуальных средств разработки и отладки наподобие имеющихся в C++Builder. Поэтому при принятии решения о создании тех или иных хранимых процедур не мешает оценить возможные трудозатраты — иногда может оказаться, что они не стоят ожидаемого эффекта.

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

Использование предварительной подготовки запросов

При использовании компонентов TQuery нередко бывает полезно использовать метод Prepare(), особенно если компонент TQuery содержит параметризованный запрос. Метод Prepare() осуществляет пересылку запроса на сервер, где он оптимизируется и компилируется, а при открытии запроса на сервер в этом случае посылаются только его параметры. Особенно заметным повышение производительности может оказаться тогда, когда параметризованные запросы с различными значениями параметров повторяются часто — в этом случае повторная подготовка запроса не потребуется. Если же метод Prepare() не вызывается явно, он будет автоматически вызываться неявно каждый раз при пересылке параметров, инициируя пересылку всего текста запроса на сервер.

Что каcается передаваемых на сервер параметров запроса, их число и объем рекомендуется минимизировать точно так же, как и в случае параметров хранимых процедур.

Использование представлений (View) и параметризованных запросов.

Нередко начинающие программисты используют динамическое создание запросов на этапе выполнения, изменяя содержимое строкового массива, содержащегося в свойстве SQL компонента TQuery (например, периодически модифицируя предложение WHERE). При часто повторяющихся запросах такого типа это не самый оптимальный способ пересылки запросов на сервер, так как в этом случае обязательно осуществляется предварительная подготовка запросов, заключающаяся в пересылке всего текста на сервер, а также оптимизации и компиляции его сервером. Более предпочтительным в этом случае является использование параметризованных запросов и метода Prepare(), либо использование представлений (View) сервера, представляющих собой не что иное как хранимый на сервере заранее скомпилированный запрос. В последнем случае можно избежать не только лишних повторных компиляций запроса сервером, но и излишней перегрузки клиента генерацией запросов.

Использование свойства UpdateMode

Свойство UpdateMode компонентов TDBDataSet определяет состав оператора WHERE, генерируемого BDE при обновлении данных. Рассмотрим, каким получится оператор WHERE при редактировании поля SYMBOL содержащейся на сервере Oracle Workgroup Server копии таблицы HOLDINGS из входящей в комплект поставки C++Builder базы данных BCDEMOS при разных значениях этого свойства. Сгенерированные SQL-предложения можно пронаблюдать с помощью SQL Monitor.

По умолчанию значением свойства UpdateMode является UpWhereAll, и в этом случае BDE генерирует предложение WHERE, содержащее все поля таблицы. При этом сгенерированный оператор SQL, если только он не переопределен с помощью компонента TUpdateSQL, будет выглядеть следующим образом:

UPDATE «HOLDINGS» SET «SYMBOL»=:1 WHERE «ACCT_NBR»=:2 AND «SYMBOL»=:3 AND «SHARES»=:4 AND «PUR_PRICE»=:5 AND «PUR_DATE»=:6 AND «ROW >Этот способ определения изменяемых строк таблицы является самым медленным (особенно в случае таблиц с большим числом полей), но и наиболее надежным, так как практически гарантирует достоверную идентификацию записи в любой ситуации, даже в случае отсутствия ключевых полей (если, конечно, таблица удовлетворяет требованию реляционной модели, гласящему, что каждая запись должна быть уникальна и, следовательно, должна обладать уникальным набором полей).

Одним из других возможных значений этого свойства является UpWhereChanged, при котором в предложении WHERE содержатся только поля, измененные в данном запросе, и ключевые поля. В этом случае запрос имеет следующий вид:

UPDATE «HOLDINGS» SET «SYMBOL»=:1 WHERE «ROW =:3

Такой запрос выполняется быстрее, но в этом случае возможны коллизии при многопользовательской работе. Например, один пользователь считывает запись для редактирования в клиентское приложение, другой сразу после этого ее удаляет, а третий создает новую с теми же значениями изменяемых полей и теми же значениями ключевых полей. Именно эта новая запись и будет модифицироваться вместо считанной. Однако такой случай маловероятен, особенно если ставшие ненужными первичные ключи удаленных записей какое-то время не используются (например, при создании ключей с помощью генераторов последовательностей).

Третьим возможным значением свойства UpdateMode является UpWhereKeyOnly. В этом случае предложение WHERE содержит только ключевое поле:

UPDATE «HOLDINGS» SET «SYMBOL»=:1 WHERE «ROW >Хотя это самый быстрый способ обновления данных по сравнению с двумя предыдущими случаями, он в общем случае небезопасен. В этом случае возникновение ситуации, когда модифицируемое поле окажется измененным другим пользователем, никак не контролируется, что может привести к непредсказуемым результатам при многопользовательском редактировании данных. Поэтому применение значения UpWhereKeyOnly допустимо только в том случае, когда вероятность одновременной модификации одной и той же записи несколькими пользователями крайне мала.

Повышение эффективности SQL-запросов

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

Если требуется определить наличие в таблице записей, удовлетворяющих какому-либо условию, следует предпочесть использование предиката EXIST запросу, вычисляющему число таких записей. Запрос вида

SELECT * FROM WHERE (SELECT COUNT (*) FROM WHERE ) >0
заставит сервер при выполнении внутреннего подзапроса перебрать все строки таблицы, проверяя соответствие каждой записи указанному условию, тогда как запрос вида

SELECT * FROM WHERE EXISTS (SELECT * FROM WHERE )
заставит сервер перебирать записи до нахождения первой записи, удовлетворяющей указанному условию. Лишний перебор записей на сервере, естественно, занимает некоторое время — чудес не бывает.

Многие приемы оптимизации связаны с использованием индексов. Если какое-либо поле таблицы часто используется в предложении WHERE, сравнивающем его значение с какой-либо константой или параметром, наличие индекса для этого поля ускоряет подобные операции. По этой же причине рекомендуется индексировать внешние ключи у таблиц с большим числом записей. Однако следует иметь в виду, что поддержка индексов замедляет операции вставки записей, поэтому при проектировании данных следует взвесить все «за» и «против» создания индексов, а еще лучше — провести соответствующее тестирование, заполнив таблицы случайными данными (для этой цели можно написать соответствующее приложение, а еще лучше — воспользоваться готовыми средствами тестирования типа SQA Suite).

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

Особо следует отметить проблемы, связанные с использованием вложенных запросов. Дело в том, что скорость выполнения запроса существенно зависит от числа уровней вложенности подзапросов (время выполнения примерно пропорционально произведению числа записей в таблицах, используемых в подзапросах). Фактически проверка соответствия условию WHERE каждой записи из внешнего подзапроса инициирует выполнение внутреннего подзапроса, что особенно заметно сказывается при большом числе записей. В практике автора чуть более года назад был случай, когда при приведении в порядок одной из используемых корпоративных информационных систем после выполнения нескольких обычных запросов на обновление данных в таблице с несколькими десятками тысяч записей, выполнявшихся в течение нескольких секунд, был инициирован вложенный запрос на обновление данных к этой же таблице. Этот запрос выполнялся более двух часов (чего, вообще говоря, и следовало ожидать). Поэтому использовать вложенные запросы следует только в тех случаях, когда без них нельзя обойтись. Альтернативой использования вложенных запросов может служить фильтрация результатов обычного запроса в клиентском приложении либо последовательное выполнение нескольких запросов с созданием временных таблиц на сервере.

Оптимизация клиентского приложения

Методы оптимизации клиентского приложения мало чем отличаются от методов оптимизации обычных приложений C++Builder. Обычно оптимизация заключается в повышении быстродействия приложения и в снижении объема используемых ресурсов операционной системы.

Снижение количества потребляемых ресурсов возможно разными способами. Основной принцип их экономии — не использовать ресурсы впустую. Именно поэтому рекомендуется в приложениях, использующих большое количество форм, создавать их динамически и уничтожать, как только они становятся ненужными (что отличается от установок менеджера проектов по умолчанию, которые предполагают автоматическое создание всех форм сразу же). Однако при этом следует помнить, что модуль данных, содержащий компоненты доступа к данным, используемые интерфейсными элементами динамически создаваемой формы, должен быть создан до создания самой формы, дабы избежать исключительной ситуации, связанной с обращением к несуществующему объекту.

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

Еще одним способом экономии ресурсов клиентского приложения является использование более экономичных интерфейсных элементов в случаях, где это возможно (например, TDBText или TLabel вместо TDBEdit, TLabel вместо TDBMemo при отображении полей, редактирование которых не предполагается, TDBGr >Еще один прием, повышающий быстродействие клиентского приложения, заключается в сокращении числа операций, связанных с выводом данных из таблиц на экран, например, при «пролистывании» большого количества строк в компонентах типа TDBGr >Говоря об оптимизации клиент-серверных информационных систем, хотелось бы отдельно остановиться на одной очень распространенной ошибке, совершаемой программистами, имеющими большой опыт работы с настольными СУБД и средствами разработки, базирующимися на xBase-языках, такими, как Clipper, dBase, FoxPro и др. При использовании средств разработки такого рода какое-либо изменение данных в таблице согласно каким-либо правилам осуществляется обычно путем создания цикла типа:

USE HOLDINGS
GO TOP
DO WHILE !EOF()
PUR_PRICE=PUR_PRICE+10
SKIP
ENDDO
CLOSE

В приведенном фрагменте xBase-кода PUR_PRICE — имя поля таблицы HOLDINGS, подверженного изменению.

При переходе к архитектуре клиент/сервер и средствам разработки, поддерживающим SQL, поначалу возникает естественное желание продолжать писать подобный код, используя циклы и навигацию по таблице. Это не так страшно в случае использования C++Builder с настольными СУБД — локальный SQL, способный быть альтернативой в этом случае, в конечном итоге также инициирует перебор записей таблицы. Вообще говоря, то же самое происходит и при выполнении запроса типа UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE+10 на сервере баз данных, но подобный цикл является внутренним процессом сервера, в котором не задействованы ни клиент, ни сеть. Однако при использовании «клипперного» стиля программирования библиотека BDE вовсе не обязана догадываться, что имел в виду программист, написавший подобный цикл, и генерирует вовсе не такие запросы!

Илон Маск рекомендует:  Что такое код unlockresource

Рассмотрим простой пример. Создадим копию таблицы HOLDINGS.DBF из входящей в комплект поставки C++Builder базы данных DBDEMOS на каком-либо сервере баз данных, например, Personal Oracle (воспользовавшись, например, утилитой Data Migration Wizard из комплекта поставки Borland C++Builder). Затем создадим новое приложение, состоящее из одной формы, включающей компоненты TDBGrid, TTable, TDataSource, TQuery, TDBNavigator и три кнопки (рис.3).

Рис.3. Главная форма приложения для тестирования SQL-запросов, генерируемых BDE

Установим следующие значения свойств используемых компонентов (табл.1):

Компонент Свойство Значение
DBNavigator1 DataSource DataSource1
DBGrid DataSource DataSource1
Button1 Caption ‘Use SQL’
Button2: Caption ‘Update records’
Button3: Caption ‘Exit’
DataSource1 DataSet Table1
Table1 DatabaseName ORACLE7
TableName HOLDINGS
UpdateMode UpWhereKeyOnly
Table1PUR_PRICE FieldName ‘PUR_PRICE’
Query1 DatabaseName ORACLE7
SQL ‘UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE+10’

Теперь создадим обработчики событий, связанные с нажатием на кнопки. Кнопка Update records реализует аналог фрагмента xBase-кода, приведенного выше:

Временное отключение связи между DataSource1 и Table1 в данном обработчике событий сделано для того, чтобы исключить перерисовку компонента DBGr >Кнопка Use SQL реализует выполнение одиночного SQL-запроса UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE+10:

Скомпилировав приложение, запустим SQL Monitor и посмотрим, какие запросы генерируются BDE при нажатии на эти кнопки.

При использовании кнопки Update records log-файл имеет следующий вид:

  1. 14:37:08 SQL Prepare: ORACLE — UPDATE «HOLDINGS» SET «PUR_PRICE»=:1 WHERE «ROW =:2

И так далее, пока не кончатся все записи…

  1. 14:37:10 SQL Prepare: ORACLE — SELECT «ACCT_NBR» ,»SYMBOL» ,»SHARES» ,»PUR_PRICE» ,»PUR_DATE» ,»ROW =:1
  2. 14:37:10 SQL Misc: ORACLE — Set rowset size
  3. 14:37:10 SQL Stmt: ORACLE — Fetch
  4. 14:37:10 SQL Stmt: ORACLE — EOF
  5. 14:37:10 SQL Stmt: ORACLE — Close

Отметим, что это еще не самый большой набор запросов для данного случая, так как при обновлении таблицы было использовано значение UpWhereKeyOnly свойства UpdateMode компонента Table1, при котором запросы на обновление одной записи имеют минимальный набор проверяемых параметров.

При использовании кнопки Use SQL log-файл имеет совершенно другой вид:

  1. 14:35:51 SQL Prepare: ORACLE — UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE-10
  2. 14:35:51 SQL Transact: ORACLE — Set autocommit on/off
  3. 14:35:51 SQL Execute: ORACLE — UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE-10 14:35:51 SQL Stmt: ORACLE — Close

Остальные SQL-запросы, содержащиеся в log-файле, генерируются BDE при выполнении метода Refresh() компонента Table1:

  1. 14:35:51 SQL Prepare: ORACLE — SELECT «ACCT_NBR» ,»SYMBOL» ,»SHARES» ,»PUR_PRICE» ,»PUR_DATE» ,»ROW > :1)) ORDER BY «ACCT_NBR» ASC
  2. 14:35:51 SQL Execute: ORACLE — SELECT «ACCT_NBR» ,»SYMBOL» ,»SHARES» ,»PUR_PRICE» ,»PUR_DATE» ,»ROWID» FROM «HOLDINGS» WHERE ((«ACCT_NBR» IS NULL OR «ACCT_NBR»> :1)) ORDER BY «ACCT_NBR» ASC
  3. 14:35:51 SQL Misc: ORACLE — Set rowset size
  4. 14:35:51 SQL Stmt: ORACLE — Fetch

Если из текста обработчика события Button1Click удалить строку

то действия с 5-го по 14-е выполняться не будут. Кроме того, при нажатии на эту же кнопку несколько раз подряд log-файл будет иметь следующий вид:

  1. 14:11:36 SQL Prepare: ORACLE — UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE-10
  2. 14:11:36 SQL Execute: ORACLE — UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE-10
  3. 14:11:40 SQL Stmt: ORACLE — Reset
  4. 14:11:40 SQL Execute: ORACLE — UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE-10
  5. 14:14:17 SQL Stmt: ORACLE — Reset
  6. 14:14:17 SQL Execute: ORACLE — UPDATE HOLDINGS SET PUR_PRICE=PUR_PRICE-10
  7. 14:14:19 SQL Stmt: ORACLE — Reset

Как видим, компиляция запроса сервером осуществляется в этом случае только один раз.

Итак, мы видим, что «клипперный» стиль программирования при работе с SQL-серверами абсолютно неприемлем — он приводит к перегрузкам сервера, сети и рабочей станции одновременно, а разница в скорости выполнения заметна даже при небольшом объеме таблицы и использовании локального сервера, поэтому, анализируя причины низкой производительности приложений, стоит посмотреть — а нет ли в клиентском приложении подобных фрагментов кода?

IT-блог о веб-технологиях, серверах, протоколах, базах данных, СУБД, SQL, компьютерных сетях, языках программирования и создание сайтов.

О модели взаимодействия клиент-сервер простыми словами. Архитектура «клиент-сервер» с примерами

Привет, посетитель сайта ZametkiNaPolyah.ru! Продолжаем рубрику Сервера и протоколы. В этой записи мы поговорим о том, как работают приложения и сайты в сети Интернет, да и вообще в любой компьютерной сети. В основе работы приложения лежит так называемая модель взаимодействия клиент-сервер, которая позволяет разделять функционал и вычислительную нагрузку между клиентскими приложениями (заказчиками услуг) и серверными приложениями (поставщиками услуг).

Модель взаимодействия клиент-сервер. Архитектура «клиент-сервер».

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

Концепция взаимодействия клиент-сервер

Миллионы людей каждый день выходят в сеть Интернет, чтобы почитать новости, пообщаться с друзьями, получить полезную информацию, совершить покупку или оплатить счет. Но большая часть рядовых пользователей даже не догадывается о том, как и с помощью чего они всё это делают, да на самом деле большинству людей это и не нужно, главное, чтобы они получали услугу вовремя и качественно.

Здесь мы разберемся с концепцией, которая позволяет нам выполнять все эти действия в сети Интернет. Данная концепция получила название «клиент-сервер». Как понятно из названия, в данной концепции участвуют две стороны: клиент и сервер. Здесь всё как в жизни: клиент – это заказчик той или иной услуги, а сервер – поставщик услуг. Клиент и сервер физически представляют собой программы, например, типичным клиентом является браузер. В качестве сервера можно привести следующие примеры: все HTTP сервера (в частности Apache), MySQL сервер, локальный веб-сервер AMPPS или готовая сборка Denwer (последних два примера – это не проста сервера, а целый набор серверов).

Клиент и сервер взаимодействую друг с другом в сети Интернет или в любой другой компьютерной сети при помощи различных сетевых протоколов, например, IP протокол, HTTP протокол, FTP и другие. Протоколов на самом деле очень много и каждый протокол позволяет оказывать ту или иную услугу. Например, при помощи HTTP протокола браузер отправляет специальное HTTP сообщение, в котором указано какую информацию и в каком виде он хочет получить от сервера, сервер, получив такое сообщение, отсылает браузеру в ответ похожее по структуре сообщение (или несколько сообщений), в котором содержится нужная информация, обычно это HTML документ.

Сообщения, которые посылают клиенты получили названия HTTP запросы. Запросы имеют специальные методы, которые говорят серверу о том, как обрабатывать сообщение. А сообщения, которые посылает сервер получили название HTTP ответы, они содержат помимо полезной информации еще и специальные коды состояния, которые позволяют браузеру узнать то, как сервер понял его запрос.

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

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

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

Простая схема взаимодействия клиент-сервер

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

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

Почему веб-мастеру нужно понимать модель взаимодействия клиент-сервер

Давайте теперь ответим на вопрос: «зачем веб-мастеру или веб-разработчику понимать концепцию взаимодействия клиент-сервер?». Ответ, естественно, очевиден. Чтобы что-то делать своими руками нужно понимать, как это работает. Чтобы сделать сайт и, чтобы он правильно работал в сети Интернет или хотя бы просто работал, нам нужно понимать, как работает сеть Интернет.

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

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

Архитектура «клиент-сервер»

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

Существует два вида архитектуры взаимодействия клиент-сервер: первый получил название двухзвенная архитектура клиент-серверного взаимодействия, второй – многоуровневая архитектура клиент-сервер (иногда его называют трехуровневая архитектура или трехзвенная архитектура, но это частный случай).

Принцип работы двухуровневой архитектуры взаимодействия клиент-сервер заключается в том, что обработка запроса происходит на одной машине без использования сторонних ресурсов. Двухзвенная архитектура предъявляет жесткие требования к производительности сервера, но в тоже время является очень надежной. Двухуровневую модель взаимодействия клиент-сервер вы можете увидеть на рисунке ниже.

Двухуровневая модель взаимодействия клиент-сервер

Здесь четко видно, что есть клиент (1-ый уровень), который позволяет человеку сделать запрос, и есть сервер, который обрабатывает запрос клиента.

Если говорить про многоуровневую архитектуру взаимодействия клиент-сервер, то в качестве примера можно привести любую современную СУБД (за исключением, наверное, библиотеки SQLite, которая в принципе не использует концепцию клиент-сервер). Суть многоуровневой архитектуры заключается в том, что запрос клиента обрабатывается сразу несколькими серверами. Такой подход позволяет значительно снизить нагрузку на сервер из-за того, что происходит распределение операций, но в то же самое время данный подход не такой надежный, как двухзвенная архитектура. На рисунке ниже вы можете увидеть пример многоуровневой архитектуры клиент-сервер.

Многоуровневая архитектура взаимодействия клиент-сервер

Типичный пример трехуровневой модели клиент-сервер. Если говорить в контексте систем управления базами данных, то первый уровень – это клиент, который позволяет нам писать различные SQL запросы к базе данных. Второй уровень – это движок СУБД, который интерпретирует запросы и реализует взаимодействие между клиентом и файловой системой, а третий уровень – это хранилище данных.

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

Преимущества и недостатки архитектуры клиент-сервер

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

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

В качестве заключения нам стоит явно акцентировать внимание на том, что архитектура клиент-сервер не делит машины на только клиент или только сервер, а скорее позволяет распределить нагрузку и разделить функционал между клиентской частью и серверной.

ВИЗУАЛЬНАЯ РАЗРАБОТКА ПРИЛОЖЕНИЙ БАЗ ДАННЫХ В C++Builder

Разработка Систем Управления Базами Данных (СУБД) раньше всегда была очень трудоемким и медленным процессом, отягощенным необходимостью учитывать массу специфических деталей подсистем обслуживания различных баз данных на низком уровне. C++Builder принимает на себя выполнение этих рутинных операций позволяя сосредоточиться на решении основной задачи.

Все приложения СУБД, создаваемые в среде C++Builder, являются клиентами в архитектуре программного взаимодействия клиент/сервер. Клиент выдает запросы к серверу базы данных на получение или передачу информации. Сервер обрабатывает запросы от множества клиентов одновременно, координируя доступ к данным и их обновление.

Все приложения СУБД, создаваемые в среде C++Builder, основаны на компонентах пользовательского интерфейса с некоторой базой данных, которые предоставляют удивительно легкие в использовании средства разработки специальных приложений. Львиная доля времени процесса разработки уходит на визуальную установку свойств выбранных компонент. Удачно спроектированное приложение всегда обеспечивает простоту просмотра и редактирования данных пользователем, независимо от сложности структуры используемой модели данных. Данная глава с очевидностью покажет, что формы приложений СУБД для типично сложной системы в архитектуре взаимодействия клиент/сервер действительно могут быть созданы в интегрированной среде C++Builder весьма быстро и с малыми усилиями.

Воздействия на компоненты многогранны: их реакция на события обеспечивается стандартными методами, а установка значений свойств может производиться во время работы приложения. Таким образом, простое вначале приложение в процессе разработки постепенно усложняется, чтобы в конце концов выглядеть совершенно профессиональным программным изделием.

5.1 Организация доступа к базам данных

C++Builder организует доступ приложения к данным таким образом, чтобы полностью отстранить разработчика от специфики обслуживания конкретной базы дан

5.1.1 Механизм BDE

Ключевой механизм BDE (Borland Database Engine), обеспечивающий работу визуальных компонент баз данных, действует как интерфейс между вашим приложением и самой базой данных. BDE реализован в виде набора системных DLL файлов. Взаимодействие компонентных объектов с BDE никак не специфицирует конкретную базу данных и не зависит от реализации обмена информацией на нижнем уровне иерархии. Именно BDE обращается в свою очередь к драйверам, специфическим для базы данных указанного типа, возвращая вашему приложению запрошенные фактические данные. BDE играет роль, аналогичную контроллеру драйверов ODBC (Open Database Connectivity) производства фирмы Microsoft, изолируя приложения от нижнего уровня взаимодействия с базой данных и увеличивая общую производительность связи за счет использования кэш-памяти. Используя BDE, вы получаете доступ ко всем локальным стандартным базам данных вашего компьютера, к источникам данных ODBC и к SQL серверам баз данных в архитектуре сетевой связи клиент/сервер.

Унифицированная технология BDE применяется во всех продуктах производства корпорации Borland: C++Builder, Borland C++, Delphi, IntraBuilder и JBuilder. Чтобы получить доступ к содержимому базы данных, приложению необходимо знать только идентификатор ее псевдонима (alias).

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

Приложение с компонентами баз данных

Рис. 5.1. Структура взаимодействия приложений с базами данных.

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

5.1.2 Конфигурация BDE

При запуске утилиты конфигурации BDECFG32.EXE открывается окно, оформленное в виде блокнота с рядом страниц, выбираемых соответствующими закладками в нижней части окна (Рис. 5.2). Для каждой страницы можно получить сведения из справочной службы, нажав на кнопку Help. При первом запуске утилиты устанавливаются значения параметров конфигурации по умолчанию, а изменения будут иметь эффект при следующем запуске приложения баз данных.

Рис. 5.2. Основная страница Drivers утилиты конфигурации BDE.

5.1.2.1 Страница Drivers

Используется для модификации установок, применяемых драйверами BDE при создании, сортировке и обслуживании таблиц базы данных. В графе Driver Name перечисляются типы драйверов, инсталлированных на вашей рабочей станции. Драйверы STANDARD обеспечивают доступ к базам данных Paradox и dBASE, а прочие драйверы — соединения с серверами SQL и ODBC. В графе

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

Чтобы получить доступ к ODBC (например, к базе данных Microsoft Access), надо сначала создать соответствующий источник данных, и только потом вызвать утилиту конфигурации BDE для подключения к этому источнику. Кнопка New ODBC Driver открывает диалог добавления соединения ODBC к имеющемуся списку (Рис. 5.3). Кнопка Delete ODBC Driver разрешает вычеркнуть выбранный драйвер.

Рис. 5.3. Диалог добавления драйвера соединения ODBC.

5.1.2.2 Страница Aliases

Используется для выполнения операций вычеркивания и модификации псевдонимов баз данных типа STANDARD, SQL или ODBC. Alias Names перечисляет все имеющиеся псевдонимы. Позже вы будете использовать псевдоним для указания имени нужной базы данных в свойстве DatabaseName компонент таблицы TTable или запроса TQuery. Графа Parameters содержит, в частности, тип сервера и полный путь к каталогу, содержащему нужные таблицы. В графе Description кратко описывается назначение выбранного параметра.

Кнопка New Alias открывает диалог добавления нового псевдонима выбранного типа к имеющемуся списку (Рис. 5.4). Кнопка Delete Alias разрешает вычеркнуть выбранный псевдоним.

Рис. 5.4. Дисиог добавления псевдониме!.

5.1.2.3 Страница System

Используется для модификации установок системных и сетевых параметров, которые BDE использует при запуске приложения. Эта информация хранится в регистрационном файле Windows. В графе Parameters перечислены все прослеженные утилитой системные и сетевые параметры вместе с их текущими значениями. Чтобы изменить установку, выберите нужный параметр и измените его старое значение. В графе Description кратко описывается назначение выбранного параметра.

5.1.2.4 Страница Date

Используется для установки формата отображения даты. В графе Parameters перечислены все прослеженные утилитой параметры даты вместе с их текущими значениями. Чтобы изменить установку, выберите нужный параметр и измените его старое значение. В графе Description кратко описывается назначение выбранного параметра.

5.1.2.5 Страница Time

Используется для установки формата отображения времени. В графе Parameters перечислены все прослеженные утилитой параметры времени вместе с их текущими значениями. Чтобы изменить установку, выберите нужный параметр и измените его старое значение. В графе Description кратко описывается назначение выбранного параметра.

5.1.2.6 Страница Number

Используется для установки формата отображения числовых величин. В графе Parameters перечислены все прослеженные утилитой параметры числовых величин вместе с их текущими значениями. Чтобы изменить установку, выберите

нужный параметр и измените его старое значение. В графе Description кратко описывается назначение выбранного параметра.

5.1.3 «Живые данные»

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

Большинство систем программирования реляционных баз данных требуют написания специализированных процедур для выборки данных из таблиц и заполнения полей в соответствующих диалогах. Чтобы удостовериться, что ваша программа производит ожидаемые результаты, раньше приходилось многократно проходить по циклу редактирование => компиляция => сборка, непроизводительно расходуя время. ^

Иначе обстоит дело при работе в визуальной среде C++Builder, компоненты которой поддерживают поступление «живых данных». Когда вы поместите на форму компоненты доступа и управления, определите их свойства, отвечающие за связь с базой данных, вам будут представлены данные точно так же, как их увидит пользователь. C++Builder объединяет три этапа разработки в единый производственный процесс. В результате удается строить СУБД, базирующиеся на текущих требованиях заказчика, вместе с тем гибкие настолько, чтобы быстро адаптировать их к новым запросам пользователей.

Форма приложения будет выглядеть одинаково на стадии проектирования и во время работы программы. Вы сможете производить необходимые коррекции экранного представления базы данных и запросов к ней, даже не компилируя программу. Способность интерактивного испытания запросов ставит процесс разработки СУБД на самый высокий качественный уровень.

5*2 Использование визуальных компонент

Одним из важнейших достоинств интегрированной среды C++Builder является наличие удобных средств быстрой визуальной разработки приложений СУБД -специализированных компонент баз данных. В отличие от разделяемых элементов управления VBX, C++Builder компилирует компоненты в единую исполняемую программу, что существенно повышает ее надежность и быстродействие. Только очень опытные программисты способны создать программу подобного уровня качества и гибкости, используя исключительно прямые обращения к соответствующим функциям Windows API. При таком подходе даже простое приложение требует написания непомерного по объему кода.

C++Builder предоставляет разработчикам интерфейсные элементы баз данных из Библиотеки Визуальных Компонент на следующих двух вкладках Палитры компонент:

• Компоненты управления данными Data Control (такие как область редактирования TDBEdit или сетка TDBGrid) обеспечивают отображение и редактирования записей на форме приложения.

• Компоненты доступа к данным Data Access (такие как таблица TTable или запрос TQuery) адресуют фактические данные, хранящиеся в файле базы данных, а компонента источника TDataSource служит как интерфейс межкомпонентной связи.

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

C++Builder поддерживает «трехступенчатую» модель разработки приложения баз данных. В этой модели компонента управления связана с компонентой источника, а та, в свою очередь, получает фактические данные таблицы или запроса посредством механизма BDE. Рис. 5.5 показывает пример взаимосвязи компонент.

Рис. 5.5. Взаимосвязь компонент управления и доступа к содержимому баз данных.

Среднее звено, компонента TDataSource, допускает менять фактическую таблицу на стадии проектирования формы без какого бы то ни было перепрограммирования самого приложения — все отображаемые элементы связаны с источником, а не с питающими его таблицей или запросом. Кроме того, компоненты источников берут на себя задачу синхронизации обмена данными между парами таблиц по принципу master-detail.

5.2.1 Компоненты доступа к данным

В этом разделе мы подробно рассмотрим работу пяти компонент доступа, первые три из которых составляют основу любого приложения баз данных. Описание остальных компонент можно найти в главе 4.

5.2.1.1 Источники данных

Как уже было сказано, невидимая компонента TDataSource действует как интерфейс между некоторым объектом набора данных (таблица, запрос) и визуальной компонентой управления. С одной стороны, все наборы данных должны быть ассоциированы с некоторым источником. С другой стороны, каждая компонента управления должна быть ассоциирована с источником, чтобы получать данные для отображения и редактирования. Каждой компоненте набора данных должна соответствовать по меньшей мере одна компонента источника. Далее мы увидим, что все компоненты управления имеют свойство DataSource, значение которого замыкает трехступенчатую связь. Рис. 5.6 показывает свойства компоненты источника в окне Инспектора объектов:

Рис. 5.6. Свойства источники.

AutoEdit разрешает или запрещает режим редактирования записей, вводимых в поля компонент управления. Значение true включает режим редактирования по умолчанию.

DataSet определяет имя конкретного набора данных (таблицы или запроса), который питает данный источник. Можно переключаться с одного набора данных на другой «на лету», во время выполнения программы. Следующий простейший код реализует попеременное подключение объекта источника DataSourcel к таблице заказчиков «Заказчики» или к таблице «Заказы»:

if (DataSourcel->DataSet == «Заказчики»)

Чтобы синхронизировать работу компонент управления на двух формах, достаточно установить свойство DataSet на один и тот же набор данных:

void_fastcall TForm2::FormCreate (TObject *Sender)

Name определяет содержательное название данной компоненты, отличающее ее от других источников данных вашего приложения. Целесообразно давать источнику имя. которое отражает название ассоциированного с ним набора данных. Например, если вы собираетесь работать с таблицей клиентов «Clients», заданной свойством DataSet, то пусть значением свойства Name будет «ClientsSource» или подобное имя.

С компонентой TDataSource связаны три события:

OnDdlciC/iange возникает при перемещении курсора на новую запись и используется при необходимости «ручной» синхронизации поведения компонент управления.

OnStciteChcinse возникает при изменении свойства State наборов данных. Например, обработчик события (Листинг 5.1) будет отслеживать изменения состояния таблицы MyTable, выводя па форму соответствующие текстовые отметки.

void_fastcall TFormI::StateChange(TObject *Sender)

strcpytS, «Идет просмотр»);

strcpytS, «Идет редактирование»);

strcpy(S, «Идет вставка записи»);

> // Вывод текстовой строки S

Листинг 5.1. Обработчик события OnStateChange источника.

OnUpdateData возникает перед обновлением текущей записи и используется при необходимости синхронизации поведения обычных компонент с изменениями некоторого набора данных.

Компонента таблицы представляет собой один из самых фундаментальных и гибких компонентных классов. TTable устанавливает прямую связь с таблицей базы данных посредством BDE, причем все записи или столбцы этой таблицы становятся доступными для приложения — как раздельно, так и внутри определенного интервала адресов. Рис. 5.7 показывает свойства компоненты таблицы в окне Инспектора объектов:

Рис. 5.7. Свойства таблицы. Active разрешает или запрещает режим просмотра «живых данных» таблицы на этапе проектирования. Значение true или метод Open открывают просмотр таблицы. Значение false (устанавливается по умолчанию) или метод Close закрывают просмотр.

DatabaseName содержит псевдоним базы данных или полный путь к ее каталогу. Использование псевдонима всегда предпочтительнее: вы можете переназначить физический носитель данных, например, заменив локальный дисковод на сетевой. Перекомпиляция приложения не требуется — просто измените путь на вкладке Aliases в утилите конфигурации BDE.

TableName позволяет выбрать фактическое имя таблицы из выпадающего списка с именами всех таблиц в адресуемой базе данных.

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

IndexFiles открывает диалог выбора индексного файла для таблицы.

IndexName задает правило отображаемых сортировки данных, отличное от упорядочивания по первичному ключу (primary key order).

Filter позволяет устанавливать критерий фильтрации, в соответствии с которым адресуется некоторое подмножество записей таблицы.

ReadOnly управляет правами доступа в процессе выполнения программы. Значение false разрешает запись по умолчанию.

MasterFields и MasterSource участвуют в образовании связи двух таблиц (ведущей и ведомой) по принципу master-detail. Следующая процедура иллюстрирует процесс создания простой формы для демонстрационной базы данных BCDEMOS, в которой пользователь может прокручивать записи таблицы заказчиков CUSTOMER с отображением всех заказов таблицы ORDERS, сделанных текущим заказчиком:дексного файла для таблицы.

IndexName задает правило отображаемых сортировки данных, отличное от упорядочивания по первичному ключу (primary key order).

Filter позволяет устанавливать критерий фильтрации, в соответствии с которым адресуется некоторое подмножество записей таблицы.

ReadOnly управляет правами доступа в процессе выполнения программы. Значение false разрешает запись по умолчанию.

MasterFields и MasterSource участвуют в образовании связи двух таблиц (ведущей и ведомой) по принципу master-detail. Следующая процедура иллюстрирует процесс создания простой формы для демонстрационной базы данных BCDEMOS, в которой пользователь может прокручивать записи таблицы заказчиков CUSTOMER с отображением всех заказов таблицы ORDERS, сделанных текущим заказчиком:

1. Выполните команду главного меню File | New Data Module, чтобы открыть контейнер нового модуля данных DataModule2. В этот модуль поместите две пары компонент доступа к базам данных TTable и TDataSource (Рис. 5.8).

2. Установите свойства объекта ведущей таблицы Tablet

DatabaseName = BCDEMOS TableName = CUSTOMER.DB Name = CustomersTable

Рис. 5.8. Модуль данных.

3. Установите свойства объекта ведомой таблицы Table2

DatabaseName = BCDEMOS TableName = ORDERS.DB Name = OrdersTable

4. Установите свойства объекта источника DataSourcel DataSet = CustomersTable Name = CustomersSource

5. Установите свойства объекта источника DataSource2 DataSet = OrdersTable Name = OrdersSource

6. Поместите на форму пару компонент управления сеткой TDBGrid.

7. Выполните команду File | Include Unit Hdr, чтобы указать, что данная форма должна использовать созданный модуль данных.

8. Установите свойство объекта первой сетки DBGridI

DataSource = DataModule2->CustomersSource и свойство объекта второй сетки DBGrid2

9. Активизируйте таблицу OrdersTable модуля данных и установите свойство

MasterSource = CustomersSource, чтобы связать ведущую таблицу CUSTOMER с ведомой таблицей ORDERS.

10. Дважды щелкните мышью в графе значений свойства MasterFields, и в открывшемся окне дизайнера связи полей

— выберите номер заказчика CustNo (связующее поле таблиц) из выпадающего списка Available Indexes;

— задайте CustNo в списках Detail Fields и Master Fields;

— нажмите кнопку Add, чтобы добавить в список Joined Fields соединение CustNo -> CustNo;

— нажмите кнопку OK, подтверждая сделанный выбор.

11. Установите свойство Active = true для таблиц CustomersTable и OrdersTable с тем, чтобы сразу же отобразить живые данные в сетках на форме.

12. Скомпилируйте и запустите приложение. Рис. 5.9 показывает работу связанных таблиц: при прокрутке записей таблицы заказчиков вы увидите только те записи в таблице заказов, которые относятся к текущему заказчику.

Рис. 5.9. Связь таблич по принципу muster-detail.

Методы Locate и Lookup используются для поиска указанных записей как в индексных таблицах, так в таблицах с ключами: эти методы реализуют самый быстрый из возможных способов поиска в данной таблице. Если столбцы для поиска индексированы и индекс совместим с указанными опциями, используется способ индексного поиска. В противном случае методы создают для BDE соответствующий фильтр.

Locate производит поиск специфической записи и позиционирует курсор на нее. В простейшем варианте вы передаете методу название столбца для поиска, искомое значение ключа записи и флаг опций. Листинг 5.2 содержит фрагмент кода, обеспечивающего поиск в столбце «Имя» таблицы MyTable первой записи со значением «Иван». Если поиск завершился успешно. Locate возвращает значение true, и найденная запись становится текущей. Если искомая запись не найдена. Locate возвращает значение false, и позиция курсора не меняется.

Success = MyTable->Locate(«Имя», «Иван», Options);

Листинг 5.2. Простейший пример использования метода Locate.

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

bool _fastcall Locate(const AnsiString KeyFields, const Variant SKeyValues, TLocateOptions Options);

В главе 3 отмечалось, что различные типы искомых значений объявляются в шаблонном классе Variant (с помощью которого C++Builder реализует одноименный встроенный тип Delphi). Названия столбцов для поиска разделяются в текстовой строке параметра KeyFields символом точка с запятой.

Lookup выбирает значения столбца той записи, которая удовлетворяет заданным значениям поиска. Позиция курсора не меняется. В простейшем варианте вы передаете методу название столбца для поиска, искомое значение ключа записи и возвращаемые поля этой записи. Листинг 5.3 содержит фрагмент кода, обеспечивающего поиск в таблице MyTable первой записи, у которой в столбце «Фирма» имеется значение «Borland». Если поиск завершился успешно. Lookup возвращает в массиве типа Variant название фирмы, фамилию ее представителя и номер телефона. Если искомая запись не найдена. Lookup возвращает значение Null.

Results = MyTable->Lookup(«Фирма», «Borland»,

Листинг 5.3. Простейший пример использования метода Lookup.

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

Variant _fastcall Lookup(const AnsiString KeyFields, const Variant sKeyValues, const AnsiString ResultFields);

Названия столбцов для поиска разделяются в текстовой строке параметра KeyFields символом точка с запятой.

С компонентой TTable также связаны следующие методы:

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

• First, Next, Prior, Last и MoveBy используются для навигации по данным таблицы.

• SetKey, FindKey, FindNearest, GotoKey и GotoNearest используются для поиска по специфическим значениям ключей.

• Append, Insert, AppendRecord и InsertRecord добавляют новую запись к таблице. Delete вычеркивает текущую запись. Edit разрешает приложению модифицировать записи, a Post вызывает фактическое изменение содержимого базы данных.

• EditRangeStart, EditRangeEnd, SetRangeStart, SetRangeEnd, ApplyRange и SetRange устанавливают границы интервала адресов записей, возвращаемых приложению при групповом доступе.

Компоненты таблиц являются полноправными, гибкими и легкими в использовании компонентами доступа, достаточными для многих приложении СУБД. TTable возвращает все строки и столбцы единственной таблицы, если доступ не ограничивается установкой интервалов и фильтров. Компоненты запросов предоставляют разработчикам альтернативные возможности. TQuery обеспечивает доступ к нескольким таблицам одновременно и способна адресовать некоторое подмножество записей. Вид возвращаемого набора данных (result set) зависит от формы запроса, который может быть либо статическим, когда все параметры запроса задаются на стадии проектирования, или динамическим, когда параметры определяются во время выполнения программы.

Указанные действия записываются и реализуются на стандартизованном языке структурированных запросов SQL (Structured Query Language), принятом большинством удаленных серверов реляционных баз данных, таких как Sybase, Oracle, InterBase и SQL Server. Ha SQL можно сформулировать весьма изощренные запросы к базам данных. C++Builder передает запросы серверу, который интерпретирует их и возвращает результаты вашему приложению.

Рис. 5.10 показывает свойства компоненты запроса в окне Инспектора объектов:

Рис. 5.10. Свойства запроса. Active разрешает или запрещает режим просмотра «живых данных», возвращаемых запросом на этапе проектирования. Значение false устанавливается по умолчанию.

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

RequestLive разрешает или запрещает BDE сделать попытку возвратить «живой» результирующий набор. Значение false (устанавливается по умолчанию) указывает, что результаты запроса нельзя модифицировать. Значение true гарантирует возврат результирующего набора при условии, что синтаксис команды SELECT согласуется с требованиями запрашиваемых данных.

SQL используется для ввода команды SQL посредством строчного редактора списка, который открывается двойным щелчком мышью в графе значений этого свойства. Локальные и удаленные серверы баз данных обеспечивают выполнение четырех команд SQL: SELECT — для выбора существующих данных из таблиц; INSERT — для добавления

новых данных в таблицы; UPDATE — для модификации данных таблиц; DELETE -для удаления данных из таблиц. Результаты обработки запроса возвращаются приложению клиента. Следующая процедура иллюстрирует процесс создания формы со статическим запросом к таблице EMPLOYEE всей информации о служащих, зарплата которых превышает заданную величину:

1. Поместите компоненту TQuery на форму.

2. Установите псевдоним адресуемой базы данных сервера в свойстве DatabaseName. В примере используется псевдоним BCDEMOS локальной демонстрационный базы данных, содержащей, в частности, таблицу служащих некоторого предприятия.

3. Откройте строчный редактор списка, введите команду SQL

SELECT * FROM EMPLOYEE WHERE Salary>40000 и нажмите кнопку ОК.

4. Поместите на форму компоненту TDataSource и установите ее свойство DataSet = Queryl.

5. Поместите на форму компоненту управления сеткой TDBGr >

6. Установите свойство Active = true для запроса Queryl с тем, чтобы сразу же отобразить живые данные в сетке (Рис. 5.11).

Рис. 5.] ]. Форма приложения со статическим запросом к таблице служащих.

Свойство SQL имеет объектный тип TStrings и заключает список текстовых строк наподобие массива. Листинг 5.4 показывает обработчик события ButtonlClick, реализующий ввод запроса пользователем при нажатии кнопки на форме. Введенная команда SQL записывается в строчный массив (того же типа TStrings) свойства Memol->Lines компоненты редактирования TMemo. Результаты запроса можно, как и в предыдущем примере, отобразить на сетке.

void_fastcall TFormI::ButtonlClick(TObject *Sender) <

// Проверить, введена ли какая-то строка в Memol if (strcmp(Memol->Lines->Strings[0].c_str(), «») == 0) (

MessageBox(0, «No SQL Statement Entered», «Error», MB_OK) ;

// Деактивировать предыдущий запрос, если он имел место Queryl->Close ();

// Очистить свойство SQL от предыдущего запроса Queryl->SQL->Clear () ;

// Присвоить введенный в Memol текст свойству SQL Queryl->SQL->Add(Memol->Lines->Strings[0].c_str()) ;

Queryl->0pen(); // выполнить команду SQI >

catch(EDBEngineError* dbError) .// обработка ошибок BDE <

for (int i=0; i ErrorCount; i++) MessageBox (0, dbError[i].Message.c_str(), «SQL Error», MB_OK) ;

Листинг 5.4. Ввод и исполнение команды SQL.

Params позволяет специфицировать имена, типы и начальные значения параметров запроса. C++Builder дает возможность конструировать команду SQL динамического запроса с параметрами. Чтобы указать нужный параметр динамического запроса, используйте символ двоеточия перед именем этого параметра. Например, параметр номера служащего в таблице employee идентифицируется следующей командой SQL: SELECT * FROM employee WHERE EmpNo = :EmpNo.

Увидеть или поменять атрибуты выбранного параметра можно посредством диалогового редактора (Рис. 5.12), который открывается двойным щелчком мышью в графе значений этого свойства. Нажатие кнопки ОК подготавливает SQL сервер к запросу и вызывает попытку его выполнения на стадии проектирования приложения.

Рис. 5.12. Редактор параметров запроса.

Свойство Params содержи-. указатель на объект типа TParams. Поэтому изменить значение параметра во время выполнения программы можно по ^ндексу в массиве I terns объекта типа TParams: ;

или по имени параметра, посредством метода ParamByName:

Queryl->ParamFjyName («FirstName») ->AsString = «John»;

Листинг 5.5 дает законченный пример использования метода ParamByName во время исполнения программы. Параметр имени служащего FirstName идентифицируется следующей командой SQL:

SELECT * FROM EMPLOYEE WHERE FirstName = :FirstName

Заметим, что обработчик события первым делом обращается к методу подготовки запроса Prepare, посылая команду SQL серверу. Сервер выделяет ресурсы и оптимизирует динамический запрос только однажды, до первого исполнения. Все, что необходимо теперь, — это подставлять новые значения параметров и выполнять команду запроса с помощью метода Open.

void_fastcall TFormI::ButtonlClick(TObject *Sender) <

// Деактивировать предыдущий запрос, если он имел место Queryl->Close () ;

Queryl->Prepare(); // подготовить запрос // Заменить значение параметра на введенное пользователем Queryl->ParamByName(«FirstName»)->AsString =

Query 1 ->0pen(); // выполнить команду SQL >

catch(EDBEngineError* dbError) // обработка ошибок BDE <

for (int i=0; i ErrorCount; i++)

MessageBox(0, dbError[i].Message.c_str(), «SQL Error», MB_OK) ;

Листинг 5.5. Изменение значения параметра динамического запроса.

Рис. 5.13 показывает работу предыдущего примера: пользователь вводит значение параметра FirstName и в результате выполнения запроса получает список всех служащих с указанным именем.

Рис. 5.13. Результат выполнения динамического запроса с параметром.

DataSource указывает на источник другого набора данных, отличный от источника данного запроса, из которого вам надо выбрать значения текущего поля. Объект запроса будет сравнивать имя параметра в команде SQL с именами полей дочернего набора данных. Когда имена совпадают, параметр автоматически приобретает значение соответствующего поля. Следующая процедура иллюстрирует процесс создания формы, в которой запрос к таблице заказчиков CUSTOMER соединяется с таблицей заказов ORDERS по номеру заказчика CustNo:

1. Поместите компоненты TQuery и TTable на форму и установите псевдоним

BCDEMOS в их свойствах DatabaseName.

void _fastcall TPormI::DataSource2DataChange(TObject

*Sender, TField *Field) <

// Связь запроса с таблицей ORDERS установлена? if (Queryl->DataSource != NULL)

return; // да, возврат // Деактивировать предыдущий запрос, если он имел место Queryl->Close() ;

Queryl->Prepare(); // подготовить запрос // Выбрать значение параметра запроса из поля таблицы Queryl->ParamByName(«CustNo»)->AsInteger =

Query 1 ->0pen(); // выполнить команду SQL >

catch(EDBEngineError* dbError) // обработка ошибок BDE (

for (int i=0; i ErrorCount; i++)

MessageBox(0, dbError[i].Message.c_str(), «SQL Error», MB_OK) ;

Листинг 5.6. Соединение запроса с таблицей по событию источника.

Для динамического формирования текста командной строки SQL во время исполнения программы удобно использовать стандартную функцию Windows sprintf. Эта функция замещает параметры форматирования (%s, %d, %n и т.д.) передаваемыми значениями, например, в результате подстановки значений параметров форматирования:

sprintf(sqls, «SELECT * FROM %s WHERE %s = %d», tbIName, fIdName, fIdValue)

символьный массив sqls будет содержать следующую команду:

«SELECT * FROM EMPLOYEE WHERE EmpNo =3»

Листинг 5.7 иллюстрирует применение функции sprintf для формирования команды SELECT динамического запроса к таблице EMPLOYEE. Методы Clear и Add используются для занесения этой команды в свойство SQL. Поскольку подготовленный запрос использует ресурсы сервера и нет никакой гарантии, что новый запрос будет работать с данными одной и той же таблицы, C++Builder снимает готовность при любом изменении свойства SQL (т.е. устанавливает значение false свойства Prepared). При очередном исполнении запроса готовность автоматически восстанавливается.

void _fastcall TFormI::ButtonlClick(TObject *Sender)

char sqls[250]; // массив для хранения команды SQL

char fmts[50]; // массив для значения зарплаты

// Присвоить fmts значение, введенное пользователем

if ( i (strcmp(SalaryEdit->Text .c_str () , » «) ==0)) strcpytfmts, SalaryEdit->Text.c_str()) ;

strcpy(fmts, «100000»); // максимальная зарплата

// Деактивировать предыдущий запрос, если он имел место

// Очистить свойство SQL от предыдущего запроса

// Построить команду SELECT с помощью функции sprintf

sprintf(sqls, «SELECT * FROM EMPLOYEE WHERE Salary свойству SQL

Query 1 ->0pen(); // выполнить команду SELECT )

catch(EDBEngineError* dbError) // обработка ошибок BDE <

for (int i=0; i ErrorCount; i++) MessageBox(0, dbError[i].Message.c_str(), «SQL Error»,

Листинг 5.7. Формирование команды SQL с помощью функции sprintf.

Рис. 5.15 показывает работу предыдущего примера: в результате выполнения сформированного запроса пользователь получает список всех служащих, зарплата которых (выбранная из столбца Salary таблицы) оказывается меньше введенного значения.

Рис. 5.15. Результат выполнения сформированного динамического запроса.

Методы Open и ExecSQL предназначены для передачи серверу команды SQL для исполнения. В предыдущих примерах все запросы выдавали единственную команду SELECT. Результат запроса по команде select рассматривается как набор данных, точно так же, как при работе с таблицей. Существуют другие команды SQL, например, команда UPDATE, которая обновляет содержимое некоторой записи, но не возвращает какой бы то ни было результат. Для исполнения сервером таких запросов следует использовать метод ExecSQL вместо метода Open.

Листинг 5.8 представляет собой некоторое обобщение всех рассмотренных ранее операций с динамическими запросами и их параметрами.

Внимание: это приложение предназначено для управляемой модификации столбца Salary таблицы служащих EMPLOYEE из демонстрационной базы данных BCDEMOS. Изменения, внесенные командой UPDATE, необратимы, поэтому перед запуском собранного приложения позаботьтесь о том, чтобы сохранить копию оригинальной таблицы. По умолчанию С-н-Builder помещает все таблицы в каталоге инсталляции \.. .\CBuilder\Examples\Data.

void_fastcall TFormI::ButtonlClick(TObject *Sender) < •

char sqls[250]; // массив для хранения команды SELECT char fmts[50]; // массив для зарплаты и надбавки int mins, adds; // десятичные эквиваленты

// Присвоить fmts зарплату, введенную пользователем

// Деактивировать предыдущий запрос и очистить SQL

sprintf(sqls, «SELECT * FROM EMPLOYEE WHERE Salary свойству SQL

Queryl->0pen (); // выполнить команду SELECT

> catch(EDBEngineError* dbError) // обработка ошибок BDE

for (int i=0; i ErrorCount; i++) MessageBox(0, dbError[i].Message.c_str(), «SQL Error», MB_OK) ;

// Присвоить fmts надбавку [в %] , введенную пользователем

// Деактивировать предыдущий запрос и очистить SQL Queryl->Close () ;

// Присвоить команду UPDATE свойству SQL Queryl->SQL->Add(«UPDATE EMPLOYEE set Salary =

(Salary+((Salary*:adds))/100) WHERE (Salary ParamByName(«mins»)->AsInteger = mins;

< Queryl->ExecSQL(); // выполнить команду UPDATE

catch(EDBEngineError* dbError) // обработка ошибок BDE

for (int i=0; i ErrorCount; i++) MessageBox(0, dbError[i].Message.c_str(), «SQL Error», •MB_OK) ;

) // Деактивировать предыдущий запрос и очистить SQL

// Восстановить команду SELECT Queryl->SQL->Add(sqls) ;

Queryl->0pen (); // выполнить команду SELECT >

catch(EDBEngineError* dbError) // обработка ошибок BDE <

for (int i=0; i ErrorCount; i++)

MessageBox(0, dbError[i].Message.c_str(), «SQL Error», MB_OK) ;

Листинг 5.8. Использование метода ExecSQL с командой UPDATE.

Рис. 5.16 показывает пример работы приложения, вызывающего повышение заданной параметром mins минимальной зарплаты на величину процентной надбавки, определяемой параметром adds. Приложение представляет пользователю список служащих, зарплата которых осталась меньше установленного минимума. Сравните последний столбец таблицы с оригинальными значениями (Рис. 5.15).

Рис. 5.16. Результат выполнения динамического запроса с модификацией данных.

Аналогично таблице, компонента запроса также инкапсулирует следующие методы:

• First, Next, Prior, Last и MoveBy используются для навигации по результатам динамического запроса.

• Append, Insert, AppendRecord и InsertRecord добавляют новую запись к таблице. Delete вычеркивает текущую запись. Edit разрешает приложению модифицировать записи, a Post вызывает фактическое изменение содержимого базы данных.

5.2.1.4 Хранимые процедуры

Хранимая процедура представляет собой инкапсуляцию команд и данных (таблиц, индексов, областей значений) в некотором мета-объекте базы данных удаленного сервера. Компонента TStoredProc позволяет выполнить часто повторяющуюся процедуру, хранимую на сервере, и передать результаты приложению клиента.

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

Для примера рассмотрим приложение, задачей которого является вычисление единственной величины — среднеквадратичного отклонения значений по большой выборке записей. Для реализации этой функции ваше приложение должно получить по сети от сервера все значения, участвующие в вычислении, а затем произвести подсчет СКО. Цель вашего приложения — конечный результат в виде единственного числа — можно было бы достичь гораздо более эффективно с помощью хранимой на сервере процедуры, которая считывает данные «на месте» и передает именно то конечное значение, которое требовалось вашим приложением.

Рис. 5.17 показывает свойства компоненты хранимой процедуры в окне Инспектора объектов:

Рис. 5.17. Свойства хранимой процедуры. Active разрешает или запрещает режим просмотра «живых данных», возвращаемых процедурой на этапе проектирования. Значение false устанавливается по умолчанию.

DatabaseName содержит псевдоним адресуемого сервера базы данных.

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

ParamBindMode задает метод, по которому фактические параметры ставятся в соответствие формальным параметрам в описании хранимой процедуры. Значение pbByName (по умолчанию) определяет соответствие по именам, а значение pbByNumber — по порядку перечисления в процедуре.

Params используется для ввода параметров хранимой процедуры (если таковые имеются). Редактор параметров, который открывается двойным щелчком мышью в графе значений этого свойства, обращается к серверу для выборки информации о входных и выходных параметрах. Для некоторых серверов

полная информация, необходимая для запуска хранимой процедуры, может оказаться недоступной. В таком случае вам придется самому определить тип каждого параметра (Input, Output, Result), тип его данных и, возможно, значения входных параметров. Редактор параметров отображает параметры в том поряд-

ке, в котором они перечислены в описании данной хранимой процедуры (Рис. 5.18). Нажатие кнопки ОК подготавливает сервер и вызывает запуск хранимой процедуры на стадии проектирования приложения. Только база данных Oracle позволяет добавлять, вычеркивать или удалять все параметры в определении хранимой на сервере процедуры, производя таким образом ее перегрузку. Отвечающие за такие действия кнопки редактора параметров Add, Delete и Clear обычно запрещены, поскольку ваше приложение клиента не может модифицировать хранимые процедуры других серверов.

Рис. 5.18. Редактор параметров хранимой процедуры.

Аналогично запросу, свойство Params содержит указатель на массив объектного типа TParams. Поэтому изменить значение параметра во время выполнения программы можно по индексу в массиве Items объектов типа TParams:

или по имени параметра, посредством метода ParamByName:

а затем подготовить сервер методом Prepare и выполнить процедуру методом ЕхесРгос:

Хранимая процедура возвращает результаты через выходные параметры или через результирующий набор. Доступ к выходным параметрам во время выполнения программы (как и модификация значений входных параметров перед запуском хранимой процедуры) осуществляется по индексам в массиве Items объектов типа TParams:

или по имени параметра, посредством метода ParamByName:

Хранимые процедуры некоторых серверов (например, Sybase) возвращают, подобно запросу, результирующий набор, для отображения которого надо использовать подходящую компоненту управления — чаще всего сетку. Процедура проектирования формы приложения с компонентой TStoredProc аналогична той, которую мы использовали для отображения результатов запроса:

1. Установите псевдоним адресуемой базы данных сервера в свойстве DatabaseName.

2. Поместите на форму компоненту TDataSource и установите ее свойство DataSet = StoredProcl.’

3. Поместите на форму компоненту управления сеткой TDBGr >

4. Поместите компоненту TStoredProc на форму.

5. Укажите имя процедуры в свойстве StoredProcName.

6. Установите свойство Active = true для процедуры StoredProcl с тем, чтобы сразу же отобразить результаты в сетке.

7. Откройте редактор параметров, введите (если надо) их значения и нажмите кнопку ОК.

5.2.1.5 Соединения с базой данных и транзакции

Компонента TDatabase позволяет создавать в приложении локальный BDE псевдоним базы данных, таким образом не требуя его наличия в конфигурационном файле BDE. Этот локальный псевдоним может использоваться другими компонентами доступа. Кроме того, с помощью TDatabase можно разработать оригинальный процесс первого соединения с сервером (login), подавляя некоторые подсказки и автоматически подставляя значения необходимых параметров. Наконец, и что наиболее важно, TDatabase способна поддерживать одиночное соединение с базой данных, концентрируя в себе все необходимые операции для поддержания транзакции.

Классическим примером транзакции является перевод денежных средств банковских счетов. Такая транзакция обычно состоит в добавлении определенной суммы перевода к новому счету и вычитании этой суммы из исходящего счета. Если выполнение любой из этих операций терпит неудачу, весь трансферт считается незавершенным. SQL серверы дают возможность «прокручивать назад» команды при возникновении ошибки, не производя никаких изменений в базе данных. Именно управление транзакциями является функцией компоненты TDatabase. Как правило, транзакция содержит несколько команд, поэтому начало транзакции надо отметить методом StartTransaction. Как только транзакция началась, все ее исполняемые команды находятся во временном состоянии, до тех пор, пока один из методов Commit или Rollback () не отметят конец транзакции. Вызов Commit фактически модифицирует данные, а вызов Rollback отменяет всякие изменения.

Рис. 5.19 показывает свойства компоненты соединения с базой данных в окне Инспектора объектов:

Рис. 5.19. Свойства соединения с базой дачных. AliasName содержит псевдоним существующей базы данных, определенный утилитой конфигурации BDE. Указание этого свойства является альтернативой значения DriverName.

DatabaseName позволяет создать локальный псевдоним базы данных в дополнение к значениям AliasName или DriverName.

DriverName содержит имя драйвера BDE при создании локального псевдонима по значению DatabaseName. Указание этого свойства является альтернативой значения AliasName.

Params содержит строчный массив параметров одиночного соединения.

Листинг 5.9 реализует транзакцию по изменению адреса фирмы на примере связанных таблиц CUSTOMER и ORDERS. Старый адрес, введенный пользователем в область ре

дактирования EditOld, заменяется на новый, введенный в область редактирования EditNew. В этом примере компонентный объект Databasel использовался для одиночного соединения с базой данных, поддерживающего выполнение одиночной транзакции. Этот объект необходимо каким-то образом связать с псевдонимом базы данных — или установкой соответствующих свойств компоненты, или определив параметры соединения (такие как тип драйвера, имя сервера, имя пользователя , пароль) во время выполнения программы. Сначала опробуем первый способ соединения на стадии проектирования формы приложения, установив значения свойств компоненты, как показано на Рис. 5.19.

void_fastcall TFormI::ButtonlClick(TObject *Sender) <

char sqls[250]; // массив для хранения команды SQL try

// Изменить EditOld на EditNew в таблице CUSTOMER sprintf(sqls, «UPDATE CUSTOMER set Addrl = \»%s\» WHERE (Addrl = \»%s\»)», EditNew->Text.c_str(), Edit01d->Text.c_str());

// Изменить EditOld на EditNew в таблице ORDERS sprintf(sqls, «UPDATE ORDERS set ShipToAddrl = \»%s\» WHERE (ShipToAddrl = \»%s\»)», EditNew->Text.c_str(), Edit01d->Text.c_str()) ;

// Внести все изменения, сделанные до этого момента Databasel->Commit();

catch(EDBEngineError* dbError) // обработка ошибок BDE <

for (int i=0; i ErrorCount; i++) MessageBox (0, dbError[i].Message.c_str(), «SQL Error», MB_OK) ;

> catch (Exception* exception) // обработка исключений

MessageBox (0, exception->Message.c_str (), «Error», MB_OK) ;

Листинг 5.9. Транзакция, реализующая смену адреса фирмы.

Конечно, показанный на Рис. 5.20 пример прохождения транзакции в соединении с локальным сервером не имеет особой практической ценности и приводится здесь только с целью проиллюстрировать работу компоненты TDatabase.

Рис. 5.20. Результат прохождения транзакции.

Листинг 5.10 показывает, как соединиться с сервером базы данных во время выполнения программы, не создавая ее псевдонима. Ключевые моменты заключаются в том, чтобы указать DriverName и заполнить массив параметров информацией, необходимой для первого соединения (в нашем примере пользователь вводит свое имя и пароль в объекты компонент редактирования Editi и Edit2). Мы определили только те параметры соединения, которые не установлены для данного драйвера в утилите конфигурации BDE. Значение параметра SQLPASSTHRU MODE определяет один из трех возможных способов взаимодействия табличных методов Add, Append и Insert с компонентами запросов, которые соединены с той же базой данных. Использованное в примере значение NOT SHARED означает, что табличные методы и запросы используют два раздельных соединения с сервером. Сервер рассматривает их как соединения с двумя разными пользователями. До тех пор, пока транзакция не завершится, табличные методы не применяются, хотя результаты выполнения запросов могут менять содержимое базы данных, раздельно от действий активной транзакции. Два других значения SHARED NOAUTOCOMMIT и SHARED AUTOCOMMIT указывают, что табличные методы и запросы разделяют одно общее соединение с сервером. Если вам нужно включить табличные методы в транзакцию, используйте способы SHARED NOAUTOCOMMIT или NOT SHARED.

void_fasfccall TFormI::ButtonlClick(TObject *Sender) (

char name[20]; // буфер для имени пользователя char pass [20]; // буфер для пароля try

// Закрыть базу данных и установить параметры Databasel->Close() ;

Databasel->Params->Add(«SQLPASSTHRU MODE=NOT SHARED»);

sprintffname, «USER NAME=%s», Editl->Text.c_str ());

sprintf(pass, «PASSWORD=%s», Edit2->Text.c_str());

// Снова открыть базу данных и указанную таблицу Databasel->0pen() ;

catch(EDBEngineError* dbError) // обработка ошибок BDE

for (int i=0; i ErrorCount; i++) MessageBox(0, dbError[i].Message.c_str(), «SQL Error», MB_OK) ;

Листинг 5.10. Соединение с сервером без псевдонима.

Конечно, первое вхождение в локальную демонстрационную базу данных BCDEMOS не требует задания имени пользователя и пароля, однако, используя такую методику, вы сможете стандартизовать процесс соединения с обычно защищенными базами данных удаленных серверов. Рис. 5.21 иллюстрирует работу прототипа подобного приложения.

Рис. 5.21. Первое соединение с «защищенной» базой дачных.

5.2.2 Компоненты управления данными

Компоненты управления служат для отображения и редактирования наборов данных на форме в удобном для пользователя виде. Свойство DataSource замыкает трехступенчатую связь любой из компонент управления с компонентагли доступа к содержимому базы данных. Вы должны связать выбранную компоненту управления с набором данных посредством компоненты источника TDataSource, который определяется значением свойства DataSource.

Устройство и работа большинства из этих интерфейсных элементов довольно очевидны, их эквиваленты знакомы нам по вкладке Standard стандартных Windows Палитры компонент, а глава 4 содержит подробное их описание.

Остановимся на особенностях использования исключительно важной и мощной компоненты навигатора базы данных TDBNavigator. Эта компонента придает приложениям СУБД новый стандартизованный облик с панелью управления как у видеомагнитофона (Рис. 5.22).

Рчс. 5.22. Панель навигатора.

Нажимая на кнопки First, Prior, Next и Last, пользователь перемещается от записи к записи, а с помощью кнопок Insert, Delete, Edit, Post, Cancel и Refresh про-

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

Рис. 5.23 показывает свойства компоненты навигатора базы данных в окне Инспектора объектов:

Рис. 5.23. Свойства навигатора базы данных. DataSource соединяет кнопки управления панели навигатора с компонентами доступа к наборам данных через компоненту источника. Изменяя значение этого свойства во время выполнения программы, можно использовать одну и ту же компоненту для навигации по разным таблицам. Разместите на форме две компоненты редактируемого ввода DBEditI и DBEdit2, связанные с таблицами CustomersTable и OrdersTable через источники данных CustomersSource и OrdersSource, соответственно. Когда пользователь выбирает название фирмы (поле Company в DBEditI), навигатор тоже должен соединяться с источником CustomersSource, а когда активизируется номер заказа (поле OrderNo в DBEdit2), навигатор должен переключаться на источник OrdersSource. Чтобы реализовать подобную схему работы навигатора, необходимо написать обработчик события OnEnter для одного из объектов компоненты редактирования, а затем разделить это событие с другим объектом (Листинг 5.11).

VisibleButtons позволяет убрать ненужные кнопки, например, все кнопки редактирования на форме, предназначенной исключительно для просмотра данных. В приложениях клиент/сервер рекомендуется запретитькнопки First и Last, так как их нажатие может проявляться в длительном прохождении запросов.

Во время выполнения программы можно динамически прятать или вновь показывать кнопки навигатора — в ответ на определенные действия пользователя или на изменения состояния приложения. Предположим, вы предусмотрели единый навигатор для редактирования таблицы CustomersTable и для просмотра таблицы OrdersTable. Когда навигатор подключается ко второй таблице, желательно спрятать кнопки редактирования Insert, Delete, Edit, Post, Cancel и Refresh, а при подключении к первой таблице — снова показать их. Листинг 5.11 показывает законченный текст обработчика события OnEnter с добавлениями кода для манипуляций кнопками панели навигатора.

void_fastcall TFormI:: DBEditlEnter(TObject *Sender) <

btnShow “ nbFirst“nbPrior“ nbNext“nbLast“nbInsert“ nbDelete“nbEdit“nbPost“nbCancel“nbRefresh;

BorlandC++Builder1

Если при создании дистрибутива вы выбрали опцию Automatic Uninstaller, то в случае возникновения необходимости деинсталляции установленного приложения следует использовать утилиту «Установка и удаление программ» в панели управления Windows.

Таким образом, хотя InstallShield Express и не решает полностью всех проблем, возникающих при поставке приложений, с его помощью во многих случаях возможно быстрое создание дистрибутивов, удовлетворяющих современным требованиям к функциональности и дизайну инсталляционных приложений.

В заключение отметим, что поставка приложений, созданных с помощью Delphi 2.0 и Delphi 3.0, осуществляется практически точно так же, как и поставка приложений, созданных с помощью C++ Builder.

Перенос приложений C++Builder в архитектуру клиент/сервер

  • Введение
  • Немного истории
  • Особенности архитектуры клиент/сервер
  • Серверные СУБД и унаследованные данные
  • Перенос унаследованных данных с помощью Data Migration Wizard
  • Перенос унаследованных данных с использованием CASE-средств
  • Некоторые выводы

Введение

Современные средства разработки информационных систем, к числу которых относится C++Builder, ориентированы на широкую поддержку различных СУБД, как настольных, так и серверных. Построение эффективных и надежных с точки зрения сохранности и защиты данных многопользовательских информационных систем, как правило, производится с использованием последних. Создание приложений в архитектуре клиент/сервер с помощью C++ Builder обладает рядом особенностей, отличающих их от приложений, использующих настольные СУБД. Эти особенности и будут рассмотрены в ближайших нескольких статьях данного цикла.

Немного истории

Давайте отвлечемся от современных технических средств и программных продуктов, используемых при построении информационных систем, и вспомним, что происходило два десятилетия назад. В те времена при построении информационных систем самой популярной была модель “хост-компьютер + терминалы”, реализованная на базе мэйнфреймов (например, IBM-360/370, или их отечественных аналогов — компьютеров серии ЕС ЭВМ), либо на базе так называемых мини-ЭВМ (например, PDP-11, также имевших отечественный аналог – СМ-4). Характерной особенностью такой системы была полная “неинтеллектуальность” терминалов, используемых в качестве рабочих мест – их работой управлял все тот же хост-компьютер (рис.1)

Рис.1. Этап 1: модель «хост-компьютер + терминалы»

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

В чем были недостатки подобной архитектуры вычислений? Главным образом в полной зависимости пользователя от администратора хост-компьютера. Фактически пользователь (а нередко и программист) не имел возможности настроить рабочую среду под свои потребности – используемое программное обеспечение, в том числе и текстовые редакторы, компиляторы, СУБД, целиком и полностью было коллективным.

Не будет, наверное, большим преувеличением сказать, что в значительной степени именно этот недостаток подобных систем привел к бурному (и не прекратившемуся до сих пор) развитию индустрии персональных компьютеров. Наряду с дешевизной и простотой эксплуатации достаточно привлекательной особенностью настольных информационных систем стала так называемая персонализация рабочей среды, когда пользователь мог выбрать для себя инструменты для работы (текстовый редактор, СУБД, электронную таблицу и др.), наиболее соответствующие его потребностям. Естественно, и инструментов этих на рынке программных продуктов появилось довольно много. Именно в этот период появились электронные таблицы и настольные СУБД (dBase, FoxBase, Сlipper, Paradox и др.), нередко совмещающие в себе собственно СУБД и средства разработки приложений, использующих базы данных.

Рис.2. Этап 2: автономная персональная обработка данных

Следующим этапом развития архитектуры информационных систем было появление сетевых версий вышеупомянутых СУБД, позволяющих осуществлять многопользовательскую работу с общими данными в локальной сети. Этот подход сочетал в себе как удобства персонализации пользовательской среды и простоты эксплуатации, так и преимущества, связанные со вновь открывшимися возможностями совместного использования периферии (главным образом сетевых принтеров и сетевых дисков, в том числе хранящих коллективные данные). Отметим, что большинство информационных систем, реально эксплуатируемых сегодня в нашей стране, имеют именно такую архитектуру (в том числе некоторые информационные системы, реализованные на Delphi и C++Builder), и в случае не очень большого количества пользователей системы, не слишком большого объема данных и количества таблиц, невысоких требований к защите данных этот подход себя, безусловно, оправдывает.

Рис.3. Этап 3: коллективная обработка данных с использованием сетевых версий настольных СУБД и файлового сервера

Недостатки использования сетевых версий настольных СУБД обычно начинают проявляться в процессе длительной эксплуатации информационной системы, когда со временем увеличивается объем введенных пользователями данных, а иногда и число пользователей. Обычно в первую очередь замечается снижение производительности работы приложений, хотя нередко возникают и иные сбои в работе (например, разрушение индексов, нарушение ссылочной целостности данных). Причины этих явлений кроются в самой концепции хранения коллективных данных в файлах на сетевом диске и сосредоточении всей обработки данных внутри пользовательского приложения.

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

Возросший сетевой трафик – не единственная неприятность, подстерегающая администратора и разработчика подобной информационной системы. Весьма частым явлением в этом случае является нарушение ссылочной целостности данных. Возьмем уже ставший классическим пример, приводимый во всех учебниках по базам данных. Имеются две таблицы формата dBase: список заказчиков какой-либо компании, и список их заказов, связанные по какому-либо полю, например, CUST_ID (рис.4). Вполне разумными требованиями, предъявляемыми к такой БД (иногда называемыми бизнес-правилами), являются уникальность значений этого поля в списке заказчиков (иначе как узнать, чьи заказы с этим CUST_ID находятся в таблице заказов?), и отсутствие в списке заказов записей со значениями CUST_ID, отсутствующими в таблице заказчиков (то есть “ничьих” заказов). В случае dBase выполнение таких требований реализуется на уровне логики приложения. При этом практически всегда имеется возможность произвольного редактирования таблиц иными средствами (от dBase III до обычных текстовых редакторов), что может привести к нарушению этих требований. Обычно для предотвращения подобных прецедентов используются различные организационно-технические меры, например, запрещение средствами сетевой ОС доступа к файлам с таблицами иначе как из конкретного приложения. При этом полной гарантии сохранения ссылочной целостности все равно нет, так как остается вероятность так называемых незавершенных транзакций (то есть попытки согласованного изменения данных в нескольких таблицах – например, удаления заказчика вместе со всеми его заказами, во время которого произошел сбой питания, в результате чего удалилась только часть данных). Отметим также, что если информационная система содержит несколько приложений, использующих общие данные, каждое из них должно содержать код, предотвращающий некорректное с точки зрения ссылочной целостности изменение данных.

Рис.4.Пример связи «один-ко-многим»

Каким образом можно избежать подобных неприятностей? Ответ напрашивается сам собой: еще раз подумать об архитектуре информационной системы и сменить ее, если в обозримом будущем ожидаются подобные прецеденты. Использование серверных СУБД является в этом случае наиболее подходящим решением.

Особенности архитектуры клиент/сервер

Что же представляет собой архитектура клиент/ сервер? В определенной степени ее можно назвать возвратом к модели “хост-компьютер+терминалы”, так как ядром такой системы является сервер баз данных, представляющий собой приложение, осуществляющее комплекс действий по управлению данными – выполнение запросов, хранение и резервное копирование данных, отслеживание ссылочной целостности, проверку прав и привилегий пользователей, ведение журнала транзакций. При этом в качестве рабочего места может быть использован обычный персональный компьютер, что позволяет не отказываться от привычной рабочей среды.

Рис.5. Этап 4: обработка данных в архитектуре клиент/сервер

В чем преимущества клиент-серверных информационных систем по сравнению с их аналогами, созданными на основе сетевых версий настольных СУБД?

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

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

Кроме того, для описания серверных бизнес-правил в наиболее типичных ситуациях (как в примере с заказчиками и заказами) существуют весьма удобные инструменты — так называемые CASE-средства (CASE означает Computer-Aided System Engineering), позволяющие описать подобные правила, и создавать реализующие их объекты базы данных (индексы, триггеры), буквально рисуя мышью связи между таблицами без какого бы то ни было программирования. В этом случае клиентское приложение будет избавлено от значительной части кода, связанного с реализацией бизнес-правил непосредственно в приложении. Отметим также, что часть кода, связанного с обработкой данных, также может быть реализована в виде хранимых процедур сервера, что позволяет еще более «облегчить» клиентское приложение, а это означает, что требования к рабочим станциям могут быть не столь высоки. Это в конечном итоге удешевляет стоимость информационной системы даже при использовании дорогостоящей серверной СУБД и мощного сервера баз данных.

Помимо перечисленных возможностей, современные серверные СУБД обладают широкими возможностями управления пользовательскими привилегиями и правами доступа к различным объектам базы данных, резервного копирования и архивации данных, а нередко и оптимизации выполнения запросов. Они также, как правило, предоставляют возможность параллельной обработки данных, особенно в случае использования многопроцессорных компьютеров в качестве сервера баз данных.

Итак, клиент-серверная информационная система состоит в простейшем случае из трех основных компонентов:

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

Есть и более сложные реализации архитектуры клиент/сервер, например, трехуровневые информационные системы с использованием серверов приложений, но это уже тема отдельного разговора.

Серверные СУБД и унаследованные данные

Одной из наиболее распространенных проблем, связанных с модернизацией эксплуатируемых информационных систем, является использование в них данных, унаследованных от прежних версий и содержащихся, как правило, в форматах настольных СУБД. В частности, вопросы модернизации устаревших систем на основе xBase и переноса их на платформу Oracle, а также этапы модернизации с организационной точки зрения были подробно проанализированы Алексеем Ярцевым в статье «Миграция из xBase в Oracle» («Компьютер -Пресс», 1997, N 8, стр.137-140).

В данной работе хотелось бы рассмотреть некоторые технические аспекты проблемы использования унаследованных данных применительно к С++Builder.

Унаследованные данные, представляющие собой, как правило, самое ценное из устаревшей информационной системы, довольно редко удается перенести в серверную СУБД безболезненно. Причин тому может быть много: неудачное проектирование данных, нарушенная ссылочная целостность (причины таких нарушений были изложены выше), наконец, ориентация на иные способы обработки данных, характерные для настольных СУБД и не всегда приемлемые для серверов баз данных.

Основы программирования в среде C++Builder (стр. 2 )

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14

1.2. Основные достоинства системы программирования C++ Builder

Система объектно-ориентированного программирования C++Builder производства корпорации Borland предназначена для операционных систем платформы Win32. С++Builder –это законченный, гибкий инструмент RAD, сочетающий мощь современного компилятора языка С++, удобство средств визуальной разработки приложений, достоинства компонентного подхода к проектированию с открытыми возможностями пополнения имеющихся в распоряжении разработчика компонент[2].

Интегрированная среда разработки объединяет редактор форм, инспектор объектов, палитру компонент, администратор проекта и полностью интегрированные редактор кода и отладчик — инструменты быстрой разработки программных приложений, обеспечивающие полный контроль над кодом и ресурсами.

Профессиональные средства языка C++ интегрированы в визуальную среду разработки. C++Builder предоставляет быстродействующий компилятор языка Borland C++, соответствующий стандарту ANSI. Для повышения скорости работы в системе используется эффективный инкрементальный загрузчик и гибкие средства отладки как на уровне исходных инструкций, так и на уровне ассемблерных команд. Компилятор системы С++Builder поддерживает технологии шаблонов (templates), именованных областей видимости (namespaces), обработки исключительных ситуаций (exception handling), библиотеки стандартных шаблонов STL (Standard Template Library), информации о типах времени выполнения RTTI (Run Time Type Information). Инкрементальный компилятор и линковщик системы обрабатывают при повторной сборке проекта только те его строки, которые изменялись с момента предыдущей компиляции, тем самым экономя время сборки приложения.

Конструирование по способу «drag-and-drop« позволяет создавать приложение простым перетаскиванием захваченных мышью визуальных компонент из палитры компонент на форму приложения. Инспектор объектов предоставляет возможность оперировать со свойствами и событиями компонент уже на этапе разработки приложения, автоматически задавая значения свойств компонент, создавая заготовки функций обработки событий, которые необходимо наполнять кодом.

Механизмы двунаправленной разработки (two-way-tools) позволяют синхронизировать процесс визуального проектирования форм и генерацию исходного кода, когда манипулирование с визуальными средствами редактора форм или инспектора объектов приводит к автоматическим изменениям структуры программы, объявлений объектов программы.

Библиотека Визуальных Компонент VCL. Компоненты библиотеки VCL составляют основу программного инструментария программиста на С++Builder. Компонент – это объект, который своими свойствами, методами и событиями описывает поведение некоторого элемента пользовательского (кнопка, список строк в окне, меню) или программного (соединение с базой данных, сокет, таймер) интерфейса программы. Так как каждый компонент является законченным программным объектом, то, конструируя свое приложение как совокупность взаимодействующих компонент, программист избавляется от необходимости писать большие фрагменты кода – они уже реализованы разработчиками компонент. Находясь в среде объектно-ориентированного программирования C++Builder, компоненты можно использовать непосредственно, менять их свойства, облик и поведение или порождать производные элементы, обладающие нужными отличительными характеристиками. Хорошим подспорьем программисту является наличие исходных текстов библиотеки визуальных компонент, что облегчает разработку новых компонент на базе готовых примеров. C++Builder 6 версии Standard содержит более 80 компонент, версии Professional – более 150 компонент, версии Enterprise – более 200 компонент [4]. Благодаря открытости архитектуры VCL, список может быть дополнен как компонентами, приобретенными у сторонних разработчиков, так и компонентами собственной разработки.

Использование модели “свойства-методы-события” PEM , реализованное в С++ Builder как расширение языка С++, определяет внутреннюю структуру компонент, превращая их в удобный инструмент визуального проектирования. Компонент в этой модели является расширением понятия «класс» стандартного языка С++ с добавлением понятий «свойство» и «событие». Свойство является расширением понятия «компонентные данные класса», оно устанавливает способ получения и сохранения значений характеристик компонент при манипулировании ими как на этапе проектирования, так и в процессе работы программы. Событие определяет способ реакции компонента на внешние «раздражители», которыми могут стать сообщения, приходящие от пользователя, других компонент, операционной системы. Для поддержки модели PEM в язык внесены такие ключевые слова, как __property, _published, _closure и др. Подробнее о свойствах и событиях речь пойдет в главах 4 и 8.

Доступ к функциям API позволяет расширять функциональность разрабатываемых приложений за счет возможностей, предусмотренных операционной системой, которые, возможно, не реализованы компонентами VCL, но которые, таким образом, не выпадают из арсенала программиста.

Хранилище объектов является инструментом новой методики хранения и повторного использования модулей данных, объектов, форм и программной бизнес-логики. Поскольку построение нового приложения на существующем фундаменте значительно экономит временные затраты, хранилище объектов предоставляет для повторного использования готовые структуры: формы и законченные программные модули. Используя хранилище объектов, программист может начинать новый проект на твердой платформе предшествующих разработок, лишь добавляя в них фрагменты, характерные для стоящей перед ним задачи.

Поддержка промышленных стандартов ActiveX, OLE, СОМ, MAPI, Windows Sockets TCP/IP, ISAPI, NSAPI, ODBC, Unicode и MBCS существенно повышает функциональную мощь системы программирования, превращает ее в универсальное средство разработки приложений различной практической направленности.

Возможности работы с базами данных. С++Builder содержит полный набор компонент для работы с базами данных, которые вообще не требуют программирования. Разработка по способу «drag-and-drop» многократно упрощает и ускоряет обычно трудоемкий процесс программирования СУБД в архитектуре клиент/сервер. Широкий выбор компонент управления визуализацией и редактированием позволяет легко изменять вид отображаемой информации и поведение программы. Механизм BDE (Borland Database Engine) поддерживает высокопроизводительный 32-разрядный доступ к базам данных dBASE, Paradox, Sybase, Oracle, DB2, Microsoft SQL Server, Informix, InterBase, MySQL. C++Builder использует контроллер ODBC (Open Database Connectivity) производства Microsoft для связи с серверами баз данных Excel, Access, FoxPro. Начиная с версии 6 поддерживается технология SOAP для многоуровневых приложений баз данных, добавлен независимый от архитектуры BDE набор компонентов dbExress, позволяющий создавать приложения клиент/сервер, работающие с базами данных различных форматов, поддерживается технология доступа к базам данных ADO. Все это в сочетании с большим количеством визуальных компонент отображения информации из баз данных делает C++Builder мощной и гибкой средой программирования баз данных на языке С++.

Система программирования С++Builder является современным средством разработки приложений, поддерживающим компонентный подход и построенный по принципу визуального проектирования. Удобные встроенные средства проектирования и поддержка большинства современных технологий в области разработки баз данных, сетевых приложений, мультимедийных приложений превращают С++Builder в универсальный инструмент программиста любой специализации.

2. Состав системы программирования C++Builder

C++Builder представляет собой визуальную интегрированную среду программирования, включающую большой набор инструментов для проектирования приложений для операционной системы Windows. После запуска системы программирования она разворачивается в вид, представленный на рис. 2.1. (для C++Builder 6.0).

Можно выделить следующие основные элементы системы:

1. Палитра инструментов и главное меню системы, содержащие основные команды по управлению проектом и настройками системы.

2. Палитра компонент – содержит список компонентов, доступных программисту для добавления в проект.

3. Инспектор объектов – инструмент, предназначенный для управления свойствами и обработчиками событий компонент проекта на этапе разработки приложения.

4. Редактор форм – инструмент визуального представления видимых и невидимых компонент и манипулирования ими на этапе проектирования.

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

6.
Окно дерева объектов – удобный инструмент отображения компонент проекта в иерархии “владелец-подчиненный».

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

2.1. Панель инструментов и главное меню системы

Панель инструментов представляет программисту набор кнопок для быстрой подачи основных команд управления проектом: открытия и сохранения файлов, запуска и отладки, переключения между элементами среды. Панель является полностью настраиваемой, набор кнопок в ней может быть изменен по выбору программиста в пункте меню View | Toolbars. Полный список команд системы содержится в пунктах главного меню. Размер пособия не позволяет описать все пункты меню системы C++Builder, но в процессе изложения будут рассмотрены основные пункты, использующиеся для решения типовых задач проектировщика.

2.2. Палитра компонент

Палитра компонент представляет собой хранилище всех компонент, зарегистрированных в системе. Компоненты объединены в группы, каждая из которых хранится на отдельной закладке, название группы указывается в заголовке закладки (рис.2.2.).

Введение

Современная жизнь невозможна без эффективного управления. Важной категорией являются системы обработки информации, от которых во многом зависит эффективность работы любой организации или учреждения. Такая система должна:

обеспечивать получение общих или детализированных отчетов по итогам работы;

позволять легко определять тенденции изменения важнейших показателей;

обеспечивать получение информации без существенных задержек;

выполнять точный и полный анализ данных.

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

В данной курсовой работе будет спроектирована и разработана удаленная БД по технологии «Клиент-сервер». Она будет спроектирована и создана в СУБД Firebird 2.1 с использованием утилиты IBExpert, а также — в C++Builder 6.0 с помощью технологии доступа к данным InterBaseExpress и РНР.

1. Знакомство с СУБД Firebird и утилитой IBExpert;

2. Проектирование базы данных;

3. Приобретение навыков создания web-приложений для и win-приложений для доступа к БД.

4. Выбор сущностей для БД и определение связей между ними — проектирование БД;

5. Создание БД с помощью утилиты IBExpert;

6. Создание web-приложения;

7. Создание win-приложения.

Средства проектирования и разработки удаленной БД

Архитектура «клиент-сервер»

В настоящее время фактическим стандартом для многопользовательских СУБД, стала архитектура «клиент-сервер».

«Клиент-сервер» — это модель взаимодействия компьютеров в сети. Как правило, компьютеры не являются равноправными. Каждый из них имеет свое, отличное от других, назначение, играет определенную роль. Некоторые компьютеры в сети владеют и распоряжаются информационно-вычислительными ресурсами, такими как процессоры, файловая система, почтовая служба, служба печати, база данных. Другие имеют возможность обращаться к этим службам, пользуясь услугами первых. Компьютер, управляющий тем или иным ресурсом, принято называть сервером этого ресурса, а компьютер, желающий им воспользоваться — клиентом. Конкретный сервер определяется видом ресурса, которым он владеет. Так, если ресурсом являются базы данных, то речь идет о сервере баз данных, назначение которого — обслуживать запросы клиентов, связанные с обработкой данных; если ресурс — это файловая система, то говорят о файловом сервере или файл-сервере и т.д. В сети один и тот же компьютер может выполнять как роль клиента, так и роль сервера. Этот же принцип распространяется и на взаимодействие программ. Если одна из них выполняет некоторые функции, предоставляя другим соответствующий набор услуг, то такая программа рассматривается в качестве сервера. Программы, которые пользуются этими услугами, принято называть клиентами. Если предполагается, что проектируемая информационная система будет построена по технологии «клиент-сервер», то это означает, что часть функций прикладной программы будет реализована в программе-клиенте, другая — в программе-сервере, причем для их взаимодействия будет определен некоторый протокол.

Клиент-серверная СУБД позволяет обмениваться клиенту и серверу минимально необходимыми объёмами информации. Клиент может выполнять функции предварительной обработки перед передачей информации серверу, но в основном его функции заключаются в организации доступа пользователя к серверу. В большинстве случаев клиент-серверная СУБД гораздо менее требовательна к пропускной способности компьютерной сети, чем файл-серверная СУБД. Поэтому на данное время наиболее предпочтительной из технологий доступа к распределенным БД является именно «клиент-серверная» технология.

СУБД FireBird, основанная на технологии доступа к распределенным БД InterBase

Firebird является сервером баз данных. Мощный с минимальными требованиями к настройке и администрированию, он легко масштабируется от однопользовательских приложений до крупных корпоративных систем. Один сервер Firebird может обрабатывать несколько независимых баз данных, каждую с множеством пользовательских соединений.

Firebird предлагает удобный путь миграции от коммерческих СУБД с закрытым исходным кодом к продуктам Open Source, в то же время предлагая разработчику намного больше свободы в создании приложений. Firebird позволяет сделать этот переход легко и быстро. СУБД Firebird имеет практически все черты, характерные лучшим серверам баз данных без нанесения значительного вреда производительности, что подтверждают многочисленные промышленные тесты.

IBExpert

IBExpert — инструмент для разработки Firebird баз данных на основе технологии InterBase. IBExpert позволяет осуществить данное проектирование с заметной легкостью, быстротой, надежностью и удобством для разработчика. IBExpert включает много инструментов и особенностей кодирования: визуальные редакторы для всех типов Базы данных, SQL-редакторы и сценарии, отладчик для хранимых процедур, генераторов и триггеров, исключения, роли, домены и многое другое.

Визуальные особенности редактирования IBExpert позволяют даже полному новичку в данной области быстро создавать базу данных и добавлять объекты в базы данных без особых трудов и временных затрат.

C++ Builder — средство разработки клиентской части и серверных Web-приложений

Разработка СУБД раньше всегда была очень трудоемким и медленным процессом, отягощенным необходимостью учитывать массу специфических деталей подсистем обслуживания различных баз данных на низком уровне. C++ Builder принимает на себя выполнение этих рутинных операций позволяя сосредоточиться на решении основной задачи.

Все приложения СУБД, создаваемые в среде C++ Builder, являются клиентами в архитектуре программного взаимодействия клиент/сервер. Клиент выдает запросы к серверу базы данных на получение или передачу информации. Сервер обрабатывает запросы от множества клиентов одновременно, координируя доступ к данным и их обновление. Все приложения СУБД, создаваемые в среде C++Builder, основаны на компонентах пользовательского интерфейса с некоторой базой данных, которые предоставляют удивительно легкие в использовании средства разработки специальных приложений. Удачно спроектированное приложение всегда обеспечивает простоту просмотра и редактирования данных пользователем, независимо от сложности структуры используемой модели данных.

Создание клиент-серверных приложений Текст научной статьи по специальности « Автоматика. Вычислительная техника»

Аннотация научной статьи по автоматике и вычислительной технике, автор научной работы — Гайнанова Р.Ш., Широкова О.А.

В статье рассматриваются способы разработки клиент-серверных приложений в среде Microsoft SQL Server 2012 на примере создания проекта «Отдел кадров», включающего базу данных «Кадры». Рассматриваются способы создания базы данных в среде SQL Server Management Studio. В проекте поддерживается работа с тремя основными типами запросов, сохраняемыми в базе данных на сервере: представления , хранимые процедуры , пользовательские функции . Созданное с использованием локальной версии сервера приложение перенесено на удаленный сетевой SQL-сервер .

Похожие темы научных работ по автоматике и вычислительной технике , автор научной работы — Гайнанова Р.Ш., Широкова О.А.,

Текст научной работы на тему «Создание клиент-серверных приложений»

Р. Ш. Гайнанова, О. А. Широкова

СОЗДАНИЕ КЛИЕНТ-СЕРВЕРНЫХ ПРИЛОЖЕНИЙ

Ключевые слова: клиент-серверные приложения, Microsoft SQL Server 2012, база данных, представления, хранимые процедуры, пользовательские функции, локальная версия сервера, удаленный сетевой SQL-сервер.

В статье рассматриваются способы разработки клиент-серверных приложений в среде Microsoft SQL Server 2012 на примере создания проекта «Отдел кадров», включающего базу данных «Кадры». Рассматриваются способы создания базы данных в среде SQL Server Management Studio. В проекте поддерживается работа с тремя основными типами запросов, сохраняемыми в базе данных на сервере: представления, хранимые процедуры, пользовательские функции. Созданное с использованием локальной версии сервера приложение перенесено на удаленный сетевой SQL-сервер.

Keywords: client-server applications, Microsoft SQL Server 2012, database, views, stored procedures, user-defined functions, a local

version of the server, a remote network SQL-server.

This article discusses how to develop a client-server application in Microsoft SQL Server 2012 environment through the creation of «Human Resources» project, which includes the database «Personnel». The methods to create a database in SQL Server Management Studio environment are considered. The project uses the work of the three main types of queries, stored in a database on the server: views, stored procedures, user-defined functions.Created using a local version of the server application is moved to a remote network SQL-server.

В статье рассматриваются способы разработки клиент-серверных приложений в среде Microsoft SQL Server 2012 [1,2,3,4,5], причем рассматривается случай, когда Microsoft SQL Server 2012 установлен на локальном компьютере. Созданное с использованием локальной версии сервера приложение будет полностью пригодно для работы с базой данных на большом сетевом SQL-сервере. После завершения разработки, переместив базу с локального компьютера на сервер и модифицировав информацию о соединении, проект можно подключить к удаленному серверу. Кроме того, использование локального варианта SQL-сервера позволяет изучить средства управления базами клиент-серверной архитектуры при наличии одного компьютера.

Программное обеспечение архитектуры «клиент-сервер» состоит из двух частей: программного обеспечения сервера и программного обеспечения пользователя — клиента. Программа-клиент выполняется на компьютере пользователя и посылает запросы к программе-серверу, которая работает на компьютере общего доступа. Основная обработка данных производится мощным сервером, а на компьютер пользователя возвращаются только результаты выполнения запроса. В такой архитектуре сервер называется сервером баз данных.

Широко известными СУБД, используемыми в архитектуре «клиент-сервер», являются Microsoft SQL Server, Oracle, Sybase SQL Server и др. Эти СУБД являются реляционными SQL-серверами баз данных. СУБД архитектуры «клиент-сервер» может включать собственную клиентскую программу. В то же время в качестве клиентов сервера баз данных могут использоваться другие СУБД. Access также может работать в качестве клиента SQL-сервера. Для взаимосвязи клиентов с сервером разработано

специальное программное обеспечение. Широко используемыми интерфейсами таких взаимосвязей являются ODBC и OLE DB. Access предоставляет несколько способов взаимодействия приложения с данными сервера на основе интерфейса ODBC.

ODBC — это стандартный интерфейс между базой данных и приложением, взаимодействующим с ней. Наличие подобного стандарта позволяет любому приложению на клиентском компьютере получать доступ к любой базе данных на сервере с помощью SQL. Приложение получает доступ к конкретной базе данных, используя специально разработанный под нее драйвер (драйвер ODBC). Интерфейс ODBC состоит из четырех функциональных компонентов, именуемых уровнями ODBC. Благодаря каждому из них достигается гибкость ODBC, позволяющая взаимодействовать любым ODBC-совместимым клиентам и серверам. Между пользователем и данными, которые он хочет получить, процесс проходит четыре уровня интерфейса ODBC: приложение, диспетчер драйверов, драйвер DLL, источник данных.

С версии 2000 Access включает средства создания клиентских приложений Microsoft SQL Server, которые позволяют не только использовать существующие на сервере базы данных, но и создавать новые и взаимодействовать с ними на основе интерфейса OLE DB. OLE DB — это архитектура компонентов базы данных, реализующая эффективный доступ по сети и через Интернет к источникам данных многих типов, в том числе реляционным источникам данных, почтовым файлам, неформатированным текстовым файлам и электронным таблицам. Набор OLE-интерфейсов обеспечивает универсальный доступ к данным различного формата. В архитектуре OLE DB приложения, получающие доступ к данным, называют потребителями данных, например Access или Visual Basic. Программы, обеспечивающие внутренний доступ к данным, называют средствами

доступа к базам данных — провайдерами, например, Microsoft OLE DB Provider for Microsoft SQL Server (рис. 1) или Microsoft Jet 4.0 OLE DB Provider для доступа к базе данных Microsoft Access внешнего потребителя. При установке Microsoft Office или Microsoft Access автоматически инсталлируются провайдеры OLE DB.

Каждый провайдер требует определения специфического набора параметров для связи с источником данных. Для того, чтобы из проекта Access подключиться к базе данных Microsoft SQL Server, нужно определить имя сервера, имя базы данных, задать способ регистрации на сервере, имя пользователя, пароль.

Требуемый тип провайдера Microsoft OLE DB Provider for SQL Server выбирается проектом по умолчанию. Эти параметры сохраняются как строка связи с базой данных сервера в проекте Access. Кроме того, они могут сохраняться в udl-файле. Файлы подключения можно использовать просто для организации и управления сведениями, необходимыми для подключения к источникам данных OLE DB. Открывается диалоговое окно Свойства связи с данными (Data Link Properties), причем выбор типа провайдера Microsoft OLE DB Provider для SQL-сервера выполняется по умолчанию.

Рис. 1 — Схема взаимодействия проекта Accessи SQL-сервера в сети

Компоненты системы SQL Server 2012

Система SQL Server 2012 играет роль платформы данных с возможностью динамической разработки, обширной бизнес-аналитикой, с выходом за пределы реляционной модели, закладывая прочный фундамент, на котором могут строить ИТ инфраструктуру малые, средние и крупные организации. В состав SQL Server 2012 входят следующие компоненты[1]:

• Служба ядра БД (Database Engine). Основные компоненты БД, уведомлений и репликации. Ядро БД является сердцем SQL Server. Репликация повышает доступность данных, распределяя их по нескольким БД и разделяя нагрузку чтения данных по нескольким выделенным серверам БД.

• Аналитические службы (Analysis Services). Обеспечивают функциональность OLAP (Online Analytical Processing) и анализа данных для приложений бизнес-аналитики. Аналитические службы позволяют организации собирать данные из разных источников, например, реляционных баз данных и обрабатывать их различными способами.

• Службы интеграции (Integration Services). Предназначены для слияния данных из разнородных источников, загрузки данных в хранилища, витрины данных и пр.

• Службы отчетов. Включают диспетчер отчетов и сервер отчетов. Представляют полномасштабную платформу для создания,

управления и распространения отчетов. Сервер отчетов построен на стандартных технологиях Microsoft Internet Information Services (IIS) и Microsoft .NET Framework и позволяет использовать для обработки и хранения отчетов сочетание возможностей SQL Server и IIS.

• Service Broker. Ключевая часть БД, обеспечивающая организацию очередей и обмена сообщениями. Очереди используются для упорядочения задач, например, запросов, чтобы они выполнялись по мере высвобождения ресурсов. Сообщения обеспечивают передачу информации от одного приложения БД другому.

Объекты базы данных SQL Server

Объектами базы данных SQL Server являются таблицы, индексы, представления, хранимые процедуры, триггеры, пользовательские функции.

Таблицы — являются основной формой для сбора информации, содержат все данные в базах данных SQL Server. Каждая таблица представляет собой тип объекта, который имеет смысл для пользователей.

Индекс — структура на диске, связанная с таблицей или представлением, которая ускоряет поиск строк таблицы или представления. Индекс содержит ключи, созданные для одного или нескольких столбцов таблицы или представления. Эти ключи хранятся в виде B-древовидной структуры, что позволяет SQL Server, быстро и эффективно находить строку или строки, связанные

с ключевыми индексами. Существуют кластерные и не кластерные индексы.

Представления являются запросами на выборку. Они выполняют извлечение данных из таблиц с помощью инструкции языка SQL SELECT и реализуют одно их основных назначений базы данных — предоставлять информацию пользователю. Результатом выполнения инструкции SELECT является таблица. Представления — это просто хранящиеся в базе данных SELECT-инструкции. С точки зрения пользователей представление — это таблица, которая не хранится постоянно в базе данных, а формируется в момент обращения к ней.

Хранимая процедура — это сохраненный набор инструкций языка Transact-SQL, выполняемый как единое целое. Хранимая процедура является специальной программой из совместно откомпилированных команд Transact-SQL, сохраняемой в базе данных SQL Server и выполняемой по вызову клиента. В хранимых процедурах могут выполняться любые инструкции Transact-SQL, в том числе инструкции добавления, изменения и удаления данных (INSERT, UPDATE и DELETE). Хранимая процедура может принимать и возвращать параметры.

Триггеры представляют собой объекты базы данных, связанные с таблицей. Во многом они похожи на хранимые процедуры и часто упоминаются как «особый вид хранимых процедур». Основное различие между триггером и хранимой процедурой в том, что триггер связан с таблицей и работает только при работе выражения INSERT, UPDATE или DELETE.

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

подпрограммами Transact-SQL, которые принимают параметры, выполняют некоторое действие, например сложный расчет, и возвращают результат этого действия в виде значения. Функции подразделяются на скалярные, возвращающие единственное значение заданного типа данных, и табличные, возвращающие таблицы (значение типа table). Вызов функции сопровождается круглыми скобками, даже если она не имеет параметров. Пользовательские функции не могут выполнять действия, изменяющие состояние базы данных. Изменениям может подвергаться только возвращаемый набор данных. Пользовательские функции делают возможным модульное программирование, не требуют повторного синтаксического анализа и оптимизации при каждом вызове, что значительно ускоряет их выполнение.

Этапы разработки клиент-серверных приложений

В статье рассматриваются этапы разработки клиент-серверных приложений [5] на примересоздания проекта «Отдел кадров», включающего базу данных «Кадры». Персонал любой организации представлен его кадрами. Состав и структура кадров постоянно меняется в соответствии и с изменением техники, технологии, организации производства и управления. Состав

кадров характеризуется следующими показателями: образовательный уровень, специальность, профессия, квалификация, стаж работы, возраст, соотношение отдельных категорий работников. Следовательно, кроме упорядочения работы кадрового отдела, предприятие получает с подобным проектом и более быстрый и качественный многофакторный анализ наиболее удобных принципов его функционирования [6].

Основным инструментом для управления БД и серверами является среда SQL Server Management Studio. Графический интерфейс этой среды упрощает управление серверами, БД и ресурсами [1]. В этой среде можно создавать базы данных. В выбранной базе данных можно создавать таблицы, представления, хранимые процедуры, функции разных типов. В окне этой среды все объекты представлены в виде дерева. Базы данных сервера, с которыми может работать пользователь, представлены в поддереве объектов SQL Server в папке «Базы данных». Папка «Безопасность» содержит список пользователей, имеющих доступ к серверу.

Разработка проекта начинается с создания на сервере БД «Кадры». В окне обозревателя объектов выполним команду «Создать базу данных». Создается таблица «Подразделения». Структура таблицы: номер подразделения (ключевое поле), название подразделения, руководитель

подразделения, телефон. Далее создается таблица «Сотрудники». Структура таблицы: ФИО, табельный номер (ключевое поле), номер подразделения (внешний ключ), должность, оклад. Кроме этого создаются множество других таблиц, например, таблица «Анкета», содержащая анкетные данные сотрудника; таблица «Табель» для ведения учета рабочего времени; «График отпусков», «Повышение квалификации» и т.д.

Новые таблицы создаются и изменяются в среде SQL Server Management Studio при помощи инструкций CREATE TABLE и ALTER TABLE. Для создания таблицы в окне БД выполним команду «Создать таблицу».

Имя столбца Тип данных Разрешить.

Назв_подразд nchar[30) \J\

Руксжод_подр nchar[30) [7\

Телефон ncharQ.0) 0

Рис. 2 — Вид окна «Создание таблицы»

Для создания таблицы «Сотрудники» введем следующую инструкцию: CREATE TABLE [dbo].[Сотрудники]( [ФИО] [nchar](30) NULL, [Таб_ном] [int] NOT NULL PRIMARY KEY, [Ном_подразд] [int] NOT NULL FOREIGN KEY REFERENCES Подразделения(Ном_подразд) ON DELETE CASCADE,

[Должность] [nchar](30) NULL, [Оклад] [money] NULL,

Ограничение FOREIGN KEY устанавливает связи между таблицами и обеспечивает ссылочную целостность. Внешний ключ одной таблицы указывает на потенциальный ключ другой. В таблицу с внешним ключом нельзя добавить строку при отсутствии соответствующего потенциального ключа. Предложение ON DELETE задает действия, производимые при попытке удаления строки, на которую ссылается внешний ключ. CASCADE- все строки с внешним ключом, ссылающимся на удаляемую строку, также удаляются.Ключевое слово REFERENCES указывает, что любое значение в столбце Ном_подразд должно находится в столбце Ном_подразд таблицы «Подразделение».

В нашем примере столбец Ном_подразд таблицы «Сотрудники» внешний ключ. Внешний ключ — это столбец одной таблицы, значения которого совпадают со значениями столбца, являющегося первичным ключом другой таблицы.

Проект Access является клиентским приложением, которое подключается к Microsoft SQL Server, расположенному в сети или на локальном компьютере. Проект Access, реализуя архитектуру «клиент-сервер», функционирует в среде Access и работает только с данными базы на SQL-сервере. Из проекта можно не только получить доступ к базе данных сервера, но и создать новую базу и ее объекты. Проект Access оснащен мощными графическими средствами, как для разработки клиентского приложения, так и базы данных на сервере. Проект Access хранится в файле типа adp (Access Data Project — проект доступа к данным). Он содержит только те объекты, которые составляют приложение: формы, отчеты, макросы и модули. В отличие от базы данных Microsoft Access проект не содержит данных или описаний структур объектов базы данных: таблицы, схемы базы данных, представления, хранимые процедуры и скалярные и табличные функции — объекты базы данных SQL-сервера — только отображаются в проекте Access.

При создании проекта «Отдел кадров» в MS Access выбирается вариант подключения к существующей на сервере базе данных[4]. Таблицы заполняются данными.

Для создания проекта Access, работающего с базой данных, размещенной на Microsoft SQL-сервере, необходимо на открывшемся после запуска Access окне в области «Новая база данных» щелкнуть на значке открытой папки, размещенном справа от поля «Имя файла»: откроется окно «Файл новой базы», в котором нужно выбрать тип файла «Проекты Microsoft Office Access (*.adp)», задать имя и папку для сохранения файла создаваемого проекта. Для завершения работы в этом окне нужно нажать кнопку OK, а в области «Новая база данных» нажать кнопку «Создать». Открывается окно, в котором выбирается один из двух вариантов: подключение к существующей на сервере базе данных или создание новой базы данных на сервере наряду с созданием проекта. Щелчком на кнопке «Да» начинается подключение к существующей на сервере базе данных. При этом открывается окно

подключения к серверу «Свойства канала передачи данных» (рис. 3), в котором, прежде всего, указывается имя сервера и способ регистрации пользователя на нем.

Далее создаются запросы для работы с БД. В проекте поддерживается работа с тремя основными типами запросов [2], сохраняемыми в базе данных на сервере: представления, хранимые процедуры, пользовательские функции. После создания они появляются в области навигации проекта. Из проекта их можно открывать, выполнять, но вносить изменения можно только на сервере.

Опишем создание встроенной функции, возвращающей табличное значение. Создадим запрос, позволяющий получить сведения о стаже работы сотрудника данного предприятия. В запрос включим поля: ФИО, Таб_номер, Дата_поступ, Стаж, где Стаж — вычисляемое поле. Стаж работы вычисляется по формуле: iif((MONTH(GetDate())-

MONTH(Анкета.Дата_поступ))>=0,Year(GetDateO)-Year(Анкета.Дата_поступ),Year(GetDateO)-Year(Анкета. Дата_поступ) -1)

Функция GetDate() возвращает текущую дату, функция MONTH — номер месяца, Year — год.

[j Свойст&а канала передачи данных

Соединение | Дополнительно | Все |

Для подключения к данным SQL Server укажите следующие сведения:

1. Выберите или введите имя сервера: B3Q2C N-8\TE5T_SQ L ^ | Обновить ] 2. Для входа в сервер использовать: (§) встроенную безопасность Windows NT О следующие имя и пароль пользователя:

^ С Пустой пароль О Разрешить сохранение пароля (§) Выберите базу данных на сервере:

© Присоединить файл базы данных с именем:

И спользуя имя файла:

QK [ Отмена | Справка |

Рис. 3 — Окно выбора параметров подключения к базе данных сервера

Для создания встроенной функции, возвращающей табличное значение, в среде SQL Server Management Stud^ окне обозревателя объектов выберем базу данных «Кадры»,откроем узел «Программирование», затем «Функции», щелкнем правой кнопкой узел «Функции, возвращающие табличное значение». В контекстном меню выберем команду «Создать встроенную функцию, возвращающую табличное значение». Указывается имя создаваемой функции (СтажРаботы), параметры не передаются. В предложении RETURNS задается ключевое слово TABLE, указывающее тип возвращаемого значения. Столбцы таблицы, возвращаемые такой функцией, определяются инструкцией SELECT. Тело функции представлено единственной командой RETURN,

после выполнения которой работа функции завершается.

CREATE FUNCTION Стаж Работы() RETURNS TABLE AS

SELECT Анкета.ФИО,Анкета.Таб_ном, Анкета.Дата_поступ, iif((MONTH(GetDate())-

MONTH(AHKeTa^aTa_noCTyn))>=0,Year(GetDate())-Year(Анкета.Дата_поступ),Year(GetDate())-Year(Анкета.Дата_поступ)-1) ASСтаж FROMdbo.Анкета )

Сохраним и выполним этот запрос. Если выполнение пройдет успешно, название функции появится в области навигации проекта. Откроем функцию в режиме таблицы. После сохранения инструкция создания встроенной функции CREATE FUNCTION меняется на инструкцию ALTER FUNCTION- инструкцию изменения встроенной функции.

Как пример опишем создание встроенной функции «Отпуск_за_данный_месяц». В функцию передается параметр — номер месяца и возвращается список сотрудников, уходящих в отпуск в данном месяце.

CREATE FUNCTION Отпуск_за_данный_месяц ( @Месяцт^ RETURNS TABLE AS

SELECT dbo.Сотрудники.ФИО, dbo.Сотрудники.Таб_ном,

FROM dbo.Сотрудники INNER JOIN

dbo.График_отпусков ON dbo.Gcтрудники.Таб_ном =

ФИО Таб но — Ном пор — Должность Начало отг | KoflJHE —

Михайлов 11 3 ИТ-специалист 2014-03-25 15

Хасанова 1 1 Бухгалтер 2014-03-25 15

Сунгатулина 15 4 Главный инженер 2015-03-20 15

— Борисов 19 4 Инженер 2015-03-25 15

Рис. 4 — Результат Отпуск_за_данный_месяц

Теперь опишем создание хранимой процедуры, возвращающей «Список сотрудников данного подразделения». Для создания хранимой процедуры в окне обозревателя объектов выберем базу данных «Кадры», откроем узел «Программирование», щелкнем правой кнопкой узел «Хранимые процедуры». В контекстном меню выберем команду «Создать хранимую процедуру». В процедуру передается параметр Номер_подразд. CREATE PROCEDURE СписокСотрудников @Номер_подразд int AS

SELECT dbo. Сотрудники.ФИО, dbo. Сотрудники. Таб_ном,

dbo. Сотрудники. Должность, dbo.Сотрудники. Оклад, dbo.

FROM dbo. Сотрудники INNER JOIN

dbo.Анкета ON dbo. Сотрудники. Таб_ном = dbo.

WHERE (Сотрудники. Ном_подразд = @Номер_подразд)

ФИО Табном • Должность • Оклад Адрес ‘ Телефон Ном_подра »

1 17 Инженер 30 000,00 Р ул.Каличева 7906546642 4

Борисов 19 Инженер зо 000,00 е ул.Толстого 7906486254 4

Рахимов 20 Практикант 20 000,00 Р ул.Мавлютовг 7941654989 4

Сунгатулина 16 Главный инже 50 000,00 9 ул.Хабиба 7906321596 4

Шакиров 18 ПОМОЩНИК ГЛё 45 000,00 Р ул.Полевая 7905046346 4

Рис. 5 — Результат процедуры сотрудников данного подразделения

Создадим главную форму управления приложением в виде формы с вкладками (рис. 6). На вкладках можно разместить формы, отчеты и удобно организовать работу специалиста с необходимыми при решении конкретных задач документами. При этом они всегда доступны и нет необходимости отвлекаться на поиск.

Для того чтобы форма открывалась сразу после открытия приложения создадим автоматически запускающийся при этом макрос АиЮЕхес. В макрос включается команда «Открыть Форму» с именем формы «Отдел кадров».

Рис. 6 — Вид одной из вкладок главной формы управления приложением

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

Выполнить перенос БД с локального сервера на сетевой можно разными способами, например, выполнив восстановление БД из резервной копииили используя возможности мастера копирования баз данных и т.д. Рассмотрим первый способ.

Первоначально действия производятся на локальном SQL-сервере, с которого осуществляется перенос данных. В среде SQL ServerManagement Studio в списке баз данных выбираем базу данных «Кадры». Открываем контекстное меню, выбираем пункт «Задачи» и ввыпадающем меню выбираем пункт «Создать резервную копию». Резервную копию будем создавать на диске.

Рис. 7 — Фрагмент окна «Резервное копирование базы данных»

Для выбора устройства, куда будет производиться копирование, нажимаем кнопку «Добавить». В открывшемся окне выбираем нужный диск и вводим имя создаваемой копии (рис. 7). Нажимаем «ОК». При успешном завершении копирования появляется сообщение: «Резервное копирование базы данных «Кадры» успешно завершено».

Дальнейшие действия производятся насетевом SQL-сервере, на которыймы переносим данные. Сетевой SQL Server 2012 работает под управлением Windows Server 2008. В Windows Server 2008 запускаем утилиту SQL ServerManagementStudio . В среде MS SQL ServerManagementStudio открываем контекстное меню на пункте «Базы данных» и выбираем пункт «Восстановить базу данных». В открывшемся окне указываем устройство, с которого будет производиться восстановление базы данных. Нажимаем кнопку с тремя точками и в открывшемся окне нажимаем кнопку «Добавить».

Указываем путь к ^bak-файлу резервной копии базы данных «Кадры». После всех настроек нажимаем кнопку «ОК». После удачного восстановления БД системный администратор для работника отдела кадров, отвечающего за работу сбазой данных, в домене Windows создает учетную запись. Затем создается имя входа и связывается с этой учетной записью. Определяются роли и разрешения на доступ для данного имени входа. Пользователь, обладающий с данной учетной записью, выбирается в качестве владельца базы данных «Кадры».

Система безопасности SQL Server строится на основе двух концепций: аутентификации и авторизации. Системный администратор, отвечающий за безопасность SQL Server, создает для каждого пользователя отдельный объект login. Этот объект содержит имя учетной записи пользователя SQL Server, его пароль, полное имя и другие атрибуты, предназначенные для управления доступом к базам данных SQL Server. Подключившись к SQL Server, пользователь получает доступ к тем базам данных, в которых зарегистрирована его учетная запись. Для того чтобы зарегистрировать учетную запись в конкретной базе данных, системный администратор

или владелец базы данных создает в ней имя пользователя базы данных и связывает ее с определенной учетной записью.

Для того чтобы ограничить возможности пользователя, системный администратор или владелец базы данных предоставляет данному пользователю базы данных (или роли, в которую он входит) разрешения на доступ к конкретным объектам и выполнение конкретных операций с этими объектами. Настройка ролей БД выполняется индивидуально для каждой БД, то есть у каждой БД свой собственный набор ролей. У одного пользователя может быть несколько ролей. Полномочия ролей могут быть следующие: добавление новых пользователей; создание, изменение и удаление объектов БД; выполнение резервного копирования БД; запрещение считывания и модификации данных; управление правом собственности, а также ролями базы данных и т.д.

Практическая значимость результатов данной работы заключается в разработкеклиент-серверного приложения в среде Microsoft SQL Server 2012.В качестве клиента SQL Server используется СУБД Access. Разработанное приложение соответствует основным критериям, предъявляемым кадровыми службами для автоматизированных систем. Созданное с использованием локальной версии сервера приложение перенесено на удаленный сетевой SQL-сервер. В работе реализован способ переноса БД с помощью резервного копирования. Рассмотрены полномочия пользователей и их ролей в БД. Определен владелец базы данных «Кадры». Владельцем созданы пользователи БД, каждый из которых наделен определенными полномочиями.

1. Станек Уильям Р. Microsoft SQL Server 2012. Справочник администратора. /СПб.: БХВ-Петербург, 2013. — 576с.

2. Аллен Тейлор. SQL для чайников, 8-е издание.: Пер. с англ. — М.: ООО «И.Д. Вильямс», 2014. — 416 с.

3. Бекаревич, Ю. Б. Самоучитель Access 2010/ Ю. Б. Бекаревич, Н. В. Пушкина. — СПб.: БХВ-Петербург, 2013. — 432 с.

4. Т. В. Зудилова, Г. Ю. Шмелева Создание запросов в Microsoft SQL Server 2008 — СПб: НИУ ИТМО, 2013. -149 с.

5. Гайнанова Р. Ш. Разработка приложения типа «клиент-сервер». //НАУКА, ОБРАЗОВАНИЕ И ИННОВАЦИИ: Сборник статей Международной научно-практической конференции (25 июня 2020г., г. Томск).ч.1/-С. 70-76.

6. Кошкина Л.Ю.,Емельянов В.М., Кошкина К. В. Проектирование реляционной базы данных для мероприятий повышения квалификации в области энергоресурсосберегающих технологий //Вестник Казан. технол. ун-та. 2014. Т. 17. № 20. С. 353-356.

Оптимизация приложений С++Builder в архитектуре клиент/сервер

Оптимизация приложений С++Builder в архитектуре клиент/сервер

Одним из главных факторов, влияющих на принятие решения о переносе информационных систем в архитектуру клиент/сервер, является потенциальная возможность повышения производительности работы пользователей, особенно в тех случаях, когда находящиеся в эксплуатации приложения не удовлетворяют требованиям, предъявляемым к скорости обработки данных ввиду их большого объема, а также высокой интенсивности и сложности запросов. Известно, что информационные системы, основанные на архитектуре клиент/сервер, могут обладать существенными преимуществами перед информационными системами, базирующимися на сетевых версиях настольных СУБД, такими, как существенно меньший сетевой трафик, меньшее время обработки запросов, меньшая ресурсоемкость клиентских приложений и меньшие трудозатраты при их разработке.

Однако сам по себе факт переноса имеющейся базы данных из настольной СУБД на какой-либо сервер баз данных с соответствующей корректировкой настроек BDE (или других средств доступа к данным) отнюдь не гарантирует повышения производительности информационной системы в целом. Представьте себе, например, базу данных, содержащую одну-единственную таблицу из сотни записей и пяти целочисленных полей, содержащуюся в Oracle Workgroup Server, функционирующем под управлением Windows NT на персональном компьютере с 16 Мб оперативной памяти, и однопользовательское приложение, использующее навигационные методы для ее редактирования. В этом случае, безусловно, проще хранить данные в таблице формата dBase или Paradox — производительность системы будет в этом случае, скорее всего, намного выше, так как такой сервер, как Oracle, требует сам по себе немало ресурсов, а объем обрабатываемых данных и технология их обработки не оправдывают затрат, связанных с приобретением, установкой и эксплуатацией серверной СУБД такого класса. Данный пример, конечно, несколько утрирует реальную ситуацию, но иногда на практике происходят и более экзотические случаи:

Итак, какие шаги нужно предпринять для того, чтобы действительно повысить эффективность работы пользователей и производительность системы в целом? Первым шагом в данном направлении является, конечно, выбор сервера. В этом случае, к сожалению, нельзя давать однозначных рекомендаций типа «возьмите Oracle, он надежен» или «возьмите IB, он недорого стоит». Выбор сервера, управляющей им операционной системы и соответствующего аппаратного обеспечения должен осуществляться с учетом реальных и потенциально ожидаемых условий эксплуатации системы, таких, как скорость роста объема данных (например, в мегабайтах в месяц), интенсивность транзакций, вероятность многопользовательского доступа к одной или соседним записям в таблицах (при высокой вероятности желательно выбрать сервер, при использовании которого можно избежать страничных блокировок), потенциальный рост интенсивности работы пользователей, наличие повышенных требований к безопасности и защите данных (некоторые серверные СУБД выпускаются в разных исполнениях, отличающихся друг от друга степенью защищенности данных), необходимость использования продуктов сторонних производителей (таких, как ODBC-драйверы, дополнительные библиотеки и утилиты и др.), наличие связанных с этим проблем (типичным примером из недавней реальной практики была, например, проблема поиска ODBC-драйвера к серверу Centura SQLBase 6.0, поддерживающего использование хранимых процедур). Не менее, чем технические, важны и финансовые аспекты этой проблемы. Планируется ли использовать для установки серверной СУБД уже имеющеся вычислительные мощности и операционную систему или следует приобрести новые? В какую сумму обойдется приобретение серверной СУБД, клиентских лицензий, аппаратного обеспечения? Сколько будет стоить администрирование этой СУБД и управляющей ей операционной системы, а также обучение будущих администраторов и программистов? Сколько подключений к серверу допускается при приобретении одной лицензии — одно, два, четыре? Каковы условия, налагаемые лицензионными соглашениями при использовании мультиплексирования соединений за счет эксплуатации серверов приложений, если в дальнейшем возможен переход к трехзвенной архитектуре? Принятие решения о выборе серверной СУБД существенно зависит от ответа на все эти вопросы, и не всегда технические аспекты или мнение разработчиков определяют в конечном итоге выбор сервера. Нередки также случаи, когда предполагается использование уже имеющейся в наличии серверной СУБД (или даже готовой базы данных).

Илон Маск рекомендует:  Псевдокласс invalid в CSS
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL