Программирование баз данных в Delphi

Многоуровневая архитектура

Разбить на страницы
Показывать лекцию целиком

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

  • Уровень данных. Этот уровень отвечает за хранение данных. Как правило, для этого уровня выделяется отдельный ПК, на котором устанавливают один из SQL -серверов, например, InterBase. Клиентские ПК непосредственно не имеют никакой связи с этим уровнем.
  • Бизнес-уровень. Этот уровень предназначен для получения данных с уровня данных, выполнения окончательной проверки данных, и служит посредником между клиентами и данными. Как правило, сервера приложений находятся именно на этом уровне.
  • Уровень представления данных. Этот уровень известен так же, как уровень графического интерфейса пользователя. На этом уровне полученные данные отображаются в таких компонентах вывода данных, как DBGrid, DBEdit, DBMemo и проч. Разумеется, этот уровень находится на клиентских ПК.
  • Взгляните на рисунок:

    (рис 28.1 ) Трехуровневая модель

    На рисунке представлены три уровня архитектуры: так называемый, "тонкий" клиент ( thin-client ), сервер приложений и сервер данных. На ПК сервера БД вместе с данными расположен один из SQL -серверов. Как видите, на клиентском ПК, помимо компонентов доступа к данным, располагается только компонент связи с сервером приложений, а довольно громоздкие механизмы доступа к данным отсутствуют. Из-за этого клиентское приложение и называется "тонким" клиентом. Такой подход не только облегчает распространение приложений, но и позволяет в качестве клиентских ПК использовать дешевые, неприхотливые компьютеры. На сервере приложений вы можете видеть область, обозначенную как " Интерфейс IAppServer ". Этот интерфейс обеспечивается специальным удаленным модулем данных, о котором дальше мы поговорим подробней. Интерфейс IAppServer используют компоненты-провайдеры TDataSetProvider на стороне сервера приложений, и компоненты TClientDataSet на стороне клиента.

    При небольшом количестве клиентов ничто не мешает нам отказаться от использования SQL -сервера, расположив данные на самом сервере приложений, и используя к ним обычный локальный доступ через механизм BDE, ADO и т.п. При этом можно использовать обычные таблицы Paradox или MS Access, например. Такой подход удобней, чем файл-серверная архитектура, поскольку позволяет не только "облегчить" пользовательское приложение, но и обеспечивает безопасность данных. Ведь пользователи не будут иметь прямого доступа к самим данным, обмен информацией будет происходить через посредника, как на рисунке ниже:

    (рис 28.2. ) Объединение уровня данных и бизнес-уровня на одном сервере

    Несмотря на кажущуюся сложность архитектуры, организовать такую модель достаточно просто. Delphi для этого предлагает технологию DataSnap (в старых версиях Delphi эта технология называлась MIDAS - Multi-tier Distributed Applications Services - Серверы многозвенных распределенных приложений ). Благодаря этой технологии, вы сможете создать простой сервер приложений буквально за минуту, не введя ни строчки кода.

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

  • Централизованная бизнес-логика. Как мы уже знаем, бизнес-логикой называют некоторые правила обработки данных. Например, удаляя запись из одной таблицы, требуется удалить связанные с ней записи других таблиц. В обычных файл-серверных или клиент-серверных приложениях, часть бизнес-логики ложилась на клиентское приложение. При необходимости изменения каких-то правил, приходилось переделывать клиентское приложение, затем тратить усилия на его распространение на клиентские ПК. Теперь же эта бизнес-логика хранится на уровне сервера приложений, и при ее изменении клиенты сразу получают возможность работать по новым правилам.
  • Архитектура "тонкого" клиента.Как известно, для получения данных из БД приложения используют один из механизмов доступа к данным - BDE, ADO, ODBC, IBX, dbExpress и т.п. Все это приводит к тому, что на ПК каждого клиента приходится устанавливать и настраивать соответствующие драйверы, а это сильно усложняет процесс распространения приложения. В многозвенной архитектуре механизмы доступа к данным располагаются на сервере приложений. Только там нужно устанавливать эти драйверы (например, BDE ). Клиентские же машины не нуждаются в них, за что и называются "тонкими".
  • Модель "портфеля" (briefcase model).Модель "портфеля" подразумевает возможность отложенной обработки данных. Представьте, что вам в выходные дни требуется проделать какую-то работу с данными. При использовании файл-серверной или клиент-серверной модели, вам для этой работы придется прибыть в офис, иначе вы не сможете получить доступа к данным. В многоуровневой модели вы можете сохранить на переносном ПК все необходимые вам данные в виде локального файла. Дома вы сможете загрузить этот файл, и провести необходимую работу с данными. Затем, прибыв в офис, вы сможете перенести эти изменения в реальную базу данных.
  • Снижение трафика сети. За счет возможности отложенной обработки данных значительно снижается нагрузка на сеть.
  • Сервер приложений

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

    C:\DataBases\ok.mdb

    Delphi поддерживает следующие технологии удаленного доступа:

  • DCOM ( Distributed Component Object Model - Распределенная компонентная модель объектов) Модель рассчитана на локальную сеть и позволяет использовать объекты, расположенные на другом ПК. Если клиентское приложение работает под управлением Windows 95 (что маловероятно в настоящее время), то придется также установить поддержку DCOM95, остальные версии Windows в этом не нуждаются. Поскольку модель является "родной" для ОС Windows, использовать ее довольно просто. Вероятно, наиболее популярная модель на сегодняшний день.
  • Сокеты - позволяют использовать сеть по протоколу TCP/IP. Эта модель, пожалуй, дает наиболее быстрое соединение, однако имеется ряд замечаний. Во-первых, программисту приходится прилагать дополнительные усилия для организации связи и слежением за возможными ошибками. Во-вторых, чтобы можно было загрузить сервер приложений, сначала на компьютере с этим сервером нужно загрузить утилиту SCKTSRVR.EXE. Эта утилита устанавливается вместе с Delphi и по умолчанию находится в папке C:\PROGRAM FILES\BORLAND\DELPHI\BIN. При загрузке программы ее ярлык появляется в трее (в правом нижнем углу экрана), и с этого момента клиентские ПК смогут соединяться с этим сервером. Обычно запуск этой утилиты прописывают на сервере в автозагрузке.
  • MTS ( Microsoft Transaction Server - Сервер транзакций Microsoft ) - основана на DCOM и имеет некоторые дополнительные возможности.
  • CORBA ( Common Object Request Broker Architecture - Общедоступная архитектура брокеров при запросе объектов).
  • SOAP ( Simple Object Access Protocol - Простой протокол доступа к объекту.)
  • Загрузите Delphi и начните новый проект. Главная форма нам совсем не понадобится, назовите ее fMain, в свойстве Caption напишите " Сервер приложений ", уменьшите ее размер (например, Height =120, Width =250) и сохраните в отдельную папку, дав модулю имя Main, а проекту в целом - MyNewServer. Основой сервера является удаленный модуль данных, который обеспечивает связь сервера с клиентами, а также является контейнером для размещения компонентов, вроде обычного Data Module. Delphi позволяет использовать следующие удаленные модули:

  • Remote Data Module - используется для серверов DCOM, сокетов и OLEnterprise ;
  • Transactional Data Module - используется для сервера MTS ;
  • CORBA Data Module - для сервера CORBA ;
  • SOAP Data Module - для сервера SOAP ;
  • WebSnap Data Module - использует Web -службы и Web -броузер в качестве сервера.
  • Помимо одного из этих удаленных модулей данных, в состав сервера приложений также входят компоненты TDataSetProvider, которые предназначены для передачи данных на клиентское приложение. Каждому набору данных (таблица, запрос), предназначенному для передачи клиентам, следует предоставить по одному компоненту TDataSetProvider.

    Важно! Следует знать, что обмен данными между сервером приложений и "тонкими" клиентами обеспечивается динамической библиотекой Midas.dll, которая должна быть зарегистрирована на компьютере сервера приложений.

    Мы будем использовать технологию DCOM, поэтому выберите команду меню File -> New -> Other, чтобы открыть окно депозитария Delphi. Перейдите на вкладку Multitier и выберите Remote Data Module. Откроется окно мастера создания удаленного модуля данных:

    (рис 28.3 ) Мастер создания удаленного модуля данных

    В первом поле " CoClass Name " нам необходимо ввести имя создаваемого модуля, назовем его MyRDM. Следующие два поля требуют более детального изучения.

    Поле Instancing требует выбора способа создания экземпляров сервера, когда клиент пытается получить доступ к данным. Заметим, что Windows автоматически загружает сервер приложений, когда начинает работать клиент. Возможны следующие способы загрузки сервера:

  • Internal - при такой модели сервер COM не сможет создаваться из внешних приложений. Используется редко, в основном, когда нужно управлять доступом с помощью промежуточного уровня прокси.
  • Single Instance - при выборе этой модели для каждого клиентского соединения будет создан свой экземпляр сервера.
  • Multiple Instance - в этой модели все клиентские соединения используют единый экземпляр сервера.
  • В этом поле оставляем способ по умолчанию Multiple Instance.

    Поле Threading Model предлагает выбрать модель потоков, что позволяет распределять соединения по отдельным потокам без необходимости применения дополнительного кода. Допустимы следующие модели:

  • Single (Одиночная) - для клиентов выделяется один поток, все клиенты работают последовательно. Выбор такой модели может оказаться неудачным в многопользовательской среде, и используется редко.
  • Apartment (Раздельная) - для каждого клиента создается собственный поток. В сочетании с Multiple Instance этот способ дает самые высокие результаты и наиболее часто применяется.
  • Free (Свободная) - один экземпляр модуля данных может одновременно отвечать на несколько запросов клиентов, используя разные потоки.
  • Both (Оба) - объединяет модели Free и Apartment.
  • Neutral (Нейтральный) - разные клиенты могут одновременно вызвать удаленный модуль данных из нескольких потоков, при этом модель COM следит, чтобы не было конфликта вызовов. Однако может возникнуть конфликт потоков, который отслеживается только в версии COM+. При отсутствии этой версии нужно использовать модель Apartment.
  • В этом поле оставляем модель по умолчанию Apartment.

    Поясним материал на схеме:

    (рис 28.4 ) Поведение сервера в зависимости от способа создания экземпляров

    Нажмите кнопку "ОК", окно Мастера создания удаленного модуля закроется, и у нас появится модуль данных MyRDM. Сохраните его на диск под именем RDM.

    В этот контейнер с вкладки ADO поместите компонент ADOConnection и две таблицы ADOTable. Щелкните дважды по ADOConnection, чтобы открыть редактор подключений. Нажмите кнопку Build, чтобы открылся список поставщиков данных. Здесь выберем " Microsoft Jet 4.0 OLE DB Provider " и нажмем копку "Далее". В следующем окне, в поле 1 поместим адрес и имя файла (вы уже поместили файл по этому адресу?):

    C:\DataBases\ok.mdb

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

    Далее нажимаем "ОК" и закрываем редактор подключений. Свойство LoginPrompt компонента переведем в False, чтобы при подключении не выходило запроса на имя пользователя и пароль. А свойство Connected переведем в True, чтобы физически подключить компонент к базе данных.

    Займемся табличными компонентами. В обеих ADOTable в свойстве Connection выберите наш ADOConnection1. У первой таблицы в свойстве TableName выберите таблицу LichData, а свойство Name переименуйте в TLichData. У второй таблицы в свойстве TableName выберите таблицу Telephones, а свойство Name переименуйте в TTelephones. Свойство Active обеих таблиц переведите в True, чтобы открыть эти наборы данных. Как видите, пока что подключение сервера к базе данных мало отличается от того, что мы проходили во второй лекции, при разработке локальной базы данных для отдела кадров. Однако дальше начинаются различия.

    Как вы помните, посредником между НД и компонентами отображения данных является компонент DataSource. Однако в серверном приложении у нас нет компонентов отображения данных, поэтому компоненты DataSource для этого нам не нужны. Однако нам нужно будет организовать связь таблиц один-ко-многим, а для этого один DataSource нам все-таки понадобится.

    Также нам понадобится посредник для связи с клиентским приложением, и этим посредником является компонент DataSetProvider, который находится на вкладке Data Access Палитры компонентов. Такой компонент требуется устанавливать к каждому набору данных ( Table или Query ), с которым будет соединяться клиентское приложение. Установите в контейнер MyRDM два таких компонента. У первого свойство Name переименуйте в DSPLichData, а в свойстве DataSet выберите таблицу TLichData. У второго свойство Name переименуйте в DSPTelephones, а в свойстве DataSet выберите таблицу TTelephones.

    Теперь установим связь главная-подчиненная между таблицами, для этого установите один компонент DataSource. Его свойство Name переименуйте в dsLichData, а в свойстве DataSet выберите таблицу TLichData. Организация связи производится в таблице TTelephones. В ее свойстве MasterSource выберите dsLichData, затем раскройте сложное свойство MasterFields. Откроется окно редактора связи:

    (рис 28.5 ) Редактор связей

    В разделе подчиненного поля выберите "Сотрудник", в разделе главного поля - "Ключ", нажмите кнопку Add, чтобы создать связь, и кнопку OK, чтобы подтвердить это. Внешний вид полученного контейнера представлен на рисунке ниже:

    (рис 28.6) Удаленный модуль данных

    Это все, сервер приложений готов. Как видите, даже не пришлось подключать удаленный модуль данных к главной форме командой File -> Use Unit. Сохраните проект и командой Run -> Run (или кнопкой Run на панели инструментов) скомпилируйте и загрузите полученную программу. При этом произошли две вещи: проект скомпилировался в выполняемую программу, а при первом запуске наш сервер зарегистрировался в реестре Windows. Теперь Windows знает, где находится наш сервер, и при необходимости сможет его автоматически загрузить.

    К слову сказать, при переносе серверного файла на другой ПК нет необходимости даже загружать эту программу, чтобы прописать ее в реестре Windows, достаточно из командной строки загрузить ее с параметром / regserver, при этом программа лишь пропишется в реестре и сразу отключится. А для удаления регистрации этого сервера из реестра нужно загрузить его с параметром / unregserver, например, так (у вас может быть другой адрес):

    C:\ MyNewServer\ MyNewServer.exe /unregserver

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

    Как уже упоминалось, для правильной работы серверов DCOM на серверном ПК должна быть установлена и зарегистрирована библиотека midas.dll. В нашем случае этого делать не нужно, так как при установке Delphi библиотека устанавливается и регистрируется автоматически. Однако если вы будете использовать созданный сервер приложений на другом ПК, где не устанавливалась Delphi, то зарегистрировать библиотеку придется вручную. Для этого на вашем ПК нужно найти файл библиотеки, он устанавливается по адресу (для Windows XP ):

    C:\Windows\System32

    Этот файл нужно скопировать на ПК, который вы собираетесь использовать в качестве сервера, по этому же адресу. В этой же папке находится утилита regsvr32.exe, которая предназначена для регистрации библиотек *.dll. Чтобы зарегистрировать нашу библиотеку, надо из командной строки (или в окне команды Пуск -> Выполнить) вызвать утилиту, передав ей в качестве параметра имя библиотеки:

    C:\Windows\System32\regsvr32 midas.dll

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

    C:\Windows\System32\regsvr32 /u midas.dll

    Не снимайте регистрацию на вашем ПК, иначе потом вы не сможете загрузить сервер приложений!

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

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

    Свойства компонента DataSetProvider
    Свойство Описание
    Constraints Если содержит True, клиенту пересылается информация о наложенных на данные ограничениях. Клиент имеет возможность организовать локальный контроль данных.
    DataSet Содержит имя связанного с компонентом набора данных ( TTable, TQuery, TStoredProc )
    Exported При значении True клиент имеет возможность использовать интерфейс IAppServer при обращении к провайдеру.
    Options Сложное раскрывающееся свойство. Определяет, какие данные будут включены в передаваемый клиенту пакет. Подробнее о параметрах этого свойства смотрите следующую таблицу.
    ResolveToDataSet Определяет, как обновляются данные. Если содержит True - то в НД, указанном в свойстве DataSet. Иначе - непосредственно в серверной БД.
    UpdateMode Определяет критерии поиска записи в наборе данных при сохранении изменений этой записи клиентом. Если значение upWhereAll, поиск записи ведется по всем полям; если upWhereChanged - по ключевым и измененным полям; если upWhereKeyOnly - только по ключевым полям.

    Параметры свойства Options компонента DataSetProvider
    Параметр Описание
    poFetchBlobsOnDemand По умолчанию, данные из BLOB полей клиенту не пересылаются, чтобы излишне не загружать трафик. Если свойство содержит True - данные пересылаются. Иначе, эта возможность отключена, и чтобы получить BLOB -данные записи, клиентское приложение должно явно использовать метод FetchBlobs.
    poFetchDetailsOnDemand Данные из вложенных или подчиненных таблиц не включаются в пакет. Чтобы их получить, клиентское приложение использует метод FetchDetails. Если свойство имеет значение True, то эти данные включаются в пакет автоматически.
    poIncFieldProps В пакет включаются такие свойства полей, как Alignment, DisplayLabel, DisplayWidth, Visible, DisplayFormat, EditFormat, MaxValue, MinValue, Currency, EditMask, DisplayValues.
    poCascadeDeletes Дает серверу распоряжение автоматически удалять каскадным методом записи из подчиненных таблиц, если пользователь удалил связанную с ними запись в главной таблице.
    poCascadeUpdates Дает серверу распоряжение автоматически изменять каскадным методом записи из подчиненных таблиц, если пользователь изменил связанную с ними запись в главной таблице.
    poReadOnly Данные клиенту предоставляются только для чтения.
    poAllowMultiRecordUpdates Параметр допускает индивидуальные обновления сразу нескольких записей. Если параметр = False, множественные обновления будут автоматически прерваны.
    poDisableInserts Параметр запрещает клиенту вставку новых записей.
    poDisableEdits Параметр запрещает клиенту редактирование записей.
    poDisableDeletes Параметр запрещает клиенту удаление записей.
    poNoReset Запрещает обновление набора данных сервера перед передачей записей клиенту.
    poAutoRefresh Разрешает автоматическое обновление записей клиента при их изменении. Для ускорения работы эта опция по умолчанию отключена.
    poPropogateChanges Обновления, сделанные в событиях BeforeUpdateRecord или AfterUpdateRecord передаются клиенту в пакете, и объединяются с клиентским набором данных.
    poAllowCommandText Предоставляет клиенту возможность отменить НД, заменяя его НД, полученным SQL -запросом.
    poRetainServerOrder Запрещает клиенту изменять сортировку записей, полученную по умолчанию.

    Некоторые полезные методы компонента DataSetProvider
    Метод Описание
    ApplyUpdates Обновляет данные. Имеет параметры: Delta - измененные, новые или удаленные записи; MaxError - максимальное количество ошибок, при котором обновление прекращается (0 - не ограничено); ErrorCount - количество допущенных ошибок. Метод возвращает клиенту набор записей, при обновлении которых произошла ошибка.
    DoDelete Вызывается для каждой записи, которая должна быть удалена.
    DoInsert Вызывается для каждой новой записи.
    DoUpdate Вызывается для каждой модифицированной записи.
    EndUpdate Вызывается в момент завершения обновлений.
    LogUpdateError Добавляет ошибочную запись в журнал ошибок, который затем передается клиентскому приложению.

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

    Страницы:

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

  • Уровень данных. Этот уровень отвечает за хранение данных. Как правило, для этого уровня выделяется отдельный ПК, на котором устанавливают один из SQL -серверов, например, InterBase. Клиентские ПК непосредственно не имеют никакой связи с этим уровнем.
  • Бизнес-уровень. Этот уровень предназначен для получения данных с уровня данных, выполнения окончательной проверки данных, и служит посредником между клиентами и данными. Как правило, сервера приложений находятся именно на этом уровне.
  • Уровень представления данных. Этот уровень известен так же, как уровень графического интерфейса пользователя. На этом уровне полученные данные отображаются в таких компонентах вывода данных, как DBGrid, DBEdit, DBMemo и проч. Разумеется, этот уровень находится на клиентских ПК.
  • Взгляните на рисунок:

    (рис 28.1 ) Трехуровневая модель

    На рисунке представлены три уровня архитектуры: так называемый, "тонкий" клиент ( thin-client ), сервер приложений и сервер данных. На ПК сервера БД вместе с данными расположен один из SQL -серверов. Как видите, на клиентском ПК, помимо компонентов доступа к данным, располагается только компонент связи с сервером приложений, а довольно громоздкие механизмы доступа к данным отсутствуют. Из-за этого клиентское приложение и называется "тонким" клиентом. Такой подход не только облегчает распространение приложений, но и позволяет в качестве клиентских ПК использовать дешевые, неприхотливые компьютеры. На сервере приложений вы можете видеть область, обозначенную как " Интерфейс IAppServer ". Этот интерфейс обеспечивается специальным удаленным модулем данных, о котором дальше мы поговорим подробней. Интерфейс IAppServer используют компоненты-провайдеры TDataSetProvider на стороне сервера приложений, и компоненты TClientDataSet на стороне клиента.

    При небольшом количестве клиентов ничто не мешает нам отказаться от использования SQL -сервера, расположив данные на самом сервере приложений, и используя к ним обычный локальный доступ через механизм BDE, ADO и т.п. При этом можно использовать обычные таблицы Paradox или MS Access, например. Такой подход удобней, чем файл-серверная архитектура, поскольку позволяет не только "облегчить" пользовательское приложение, но и обеспечивает безопасность данных. Ведь пользователи не будут иметь прямого доступа к самим данным, обмен информацией будет происходить через посредника, как на рисунке ниже:

    (рис 28.2. ) Объединение уровня данных и бизнес-уровня на одном сервере

    Несмотря на кажущуюся сложность архитектуры, организовать такую модель достаточно просто. Delphi для этого предлагает технологию DataSnap (в старых версиях Delphi эта технология называлась MIDAS - Multi-tier Distributed Applications Services - Серверы многозвенных распределенных приложений ). Благодаря этой технологии, вы сможете создать простой сервер приложений буквально за минуту, не введя ни строчки кода.

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

  • Централизованная бизнес-логика. Как мы уже знаем, бизнес-логикой называют некоторые правила обработки данных. Например, удаляя запись из одной таблицы, требуется удалить связанные с ней записи других таблиц. В обычных файл-серверных или клиент-серверных приложениях, часть бизнес-логики ложилась на клиентское приложение. При необходимости изменения каких-то правил, приходилось переделывать клиентское приложение, затем тратить усилия на его распространение на клиентские ПК. Теперь же эта бизнес-логика хранится на уровне сервера приложений, и при ее изменении клиенты сразу получают возможность работать по новым правилам.
  • Архитектура "тонкого" клиента.Как известно, для получения данных из БД приложения используют один из механизмов доступа к данным - BDE, ADO, ODBC, IBX, dbExpress и т.п. Все это приводит к тому, что на ПК каждого клиента приходится устанавливать и настраивать соответствующие драйверы, а это сильно усложняет процесс распространения приложения. В многозвенной архитектуре механизмы доступа к данным располагаются на сервере приложений. Только там нужно устанавливать эти драйверы (например, BDE ). Клиентские же машины не нуждаются в них, за что и называются "тонкими".
  • Модель "портфеля" (briefcase model).Модель "портфеля" подразумевает возможность отложенной обработки данных. Представьте, что вам в выходные дни требуется проделать какую-то работу с данными. При использовании файл-серверной или клиент-серверной модели, вам для этой работы придется прибыть в офис, иначе вы не сможете получить доступа к данным. В многоуровневой модели вы можете сохранить на переносном ПК все необходимые вам данные в виде локального файла. Дома вы сможете загрузить этот файл, и провести необходимую работу с данными. Затем, прибыв в офис, вы сможете перенести эти изменения в реальную базу данных.
  • Снижение трафика сети. За счет возможности отложенной обработки данных значительно снижается нагрузка на сеть.
  • Сервер приложений

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

    C:\DataBases\ok.mdb

    Delphi поддерживает следующие технологии удаленного доступа:

  • DCOM ( Distributed Component Object Model - Распределенная компонентная модель объектов) Модель рассчитана на локальную сеть и позволяет использовать объекты, расположенные на другом ПК. Если клиентское приложение работает под управлением Windows 95 (что маловероятно в настоящее время), то придется также установить поддержку DCOM95, остальные версии Windows в этом не нуждаются. Поскольку модель является "родной" для ОС Windows, использовать ее довольно просто. Вероятно, наиболее популярная модель на сегодняшний день.
  • Сокеты - позволяют использовать сеть по протоколу TCP/IP. Эта модель, пожалуй, дает наиболее быстрое соединение, однако имеется ряд замечаний. Во-первых, программисту приходится прилагать дополнительные усилия для организации связи и слежением за возможными ошибками. Во-вторых, чтобы можно было загрузить сервер приложений, сначала на компьютере с этим сервером нужно загрузить утилиту SCKTSRVR.EXE. Эта утилита устанавливается вместе с Delphi и по умолчанию находится в папке C:\PROGRAM FILES\BORLAND\DELPHI\BIN. При загрузке программы ее ярлык появляется в трее (в правом нижнем углу экрана), и с этого момента клиентские ПК смогут соединяться с этим сервером. Обычно запуск этой утилиты прописывают на сервере в автозагрузке.
  • MTS ( Microsoft Transaction Server - Сервер транзакций Microsoft ) - основана на DCOM и имеет некоторые дополнительные возможности.
  • CORBA ( Common Object Request Broker Architecture - Общедоступная архитектура брокеров при запросе объектов).
  • SOAP ( Simple Object Access Protocol - Простой протокол доступа к объекту.)
  • Загрузите Delphi и начните новый проект. Главная форма нам совсем не понадобится, назовите ее fMain, в свойстве Caption напишите " Сервер приложений ", уменьшите ее размер (например, Height =120, Width =250) и сохраните в отдельную папку, дав модулю имя Main, а проекту в целом - MyNewServer. Основой сервера является удаленный модуль данных, который обеспечивает связь сервера с клиентами, а также является контейнером для размещения компонентов, вроде обычного Data Module. Delphi позволяет использовать следующие удаленные модули:

  • Remote Data Module - используется для серверов DCOM, сокетов и OLEnterprise ;
  • Transactional Data Module - используется для сервера MTS ;
  • CORBA Data Module - для сервера CORBA ;
  • SOAP Data Module - для сервера SOAP ;
  • WebSnap Data Module - использует Web -службы и Web -броузер в качестве сервера.
  • Помимо одного из этих удаленных модулей данных, в состав сервера приложений также входят компоненты TDataSetProvider, которые предназначены для передачи данных на клиентское приложение. Каждому набору данных (таблица, запрос), предназначенному для передачи клиентам, следует предоставить по одному компоненту TDataSetProvider.

    Важно! Следует знать, что обмен данными между сервером приложений и "тонкими" клиентами обеспечивается динамической библиотекой Midas.dll, которая должна быть зарегистрирована на компьютере сервера приложений.

    Мы будем использовать технологию DCOM, поэтому выберите команду меню File -> New -> Other, чтобы открыть окно депозитария Delphi. Перейдите на вкладку Multitier и выберите Remote Data Module. Откроется окно мастера создания удаленного модуля данных:

    (рис 28.3 ) Мастер создания удаленного модуля данных

    В первом поле " CoClass Name " нам необходимо ввести имя создаваемого модуля, назовем его MyRDM. Следующие два поля требуют более детального изучения.

    Поле Instancing требует выбора способа создания экземпляров сервера, когда клиент пытается получить доступ к данным. Заметим, что Windows автоматически загружает сервер приложений, когда начинает работать клиент. Возможны следующие способы загрузки сервера:

  • Internal - при такой модели сервер COM не сможет создаваться из внешних приложений. Используется редко, в основном, когда нужно управлять доступом с помощью промежуточного уровня прокси.
  • Single Instance - при выборе этой модели для каждого клиентского соединения будет создан свой экземпляр сервера.
  • Multiple Instance - в этой модели все клиентские соединения используют единый экземпляр сервера.
  • В этом поле оставляем способ по умолчанию Multiple Instance.

    Поле Threading Model предлагает выбрать модель потоков, что позволяет распределять соединения по отдельным потокам без необходимости применения дополнительного кода. Допустимы следующие модели:

  • Single (Одиночная) - для клиентов выделяется один поток, все клиенты работают последовательно. Выбор такой модели может оказаться неудачным в многопользовательской среде, и используется редко.
  • Apartment (Раздельная) - для каждого клиента создается собственный поток. В сочетании с Multiple Instance этот способ дает самые высокие результаты и наиболее часто применяется.
  • Free (Свободная) - один экземпляр модуля данных может одновременно отвечать на несколько запросов клиентов, используя разные потоки.
  • Both (Оба) - объединяет модели Free и Apartment.
  • Neutral (Нейтральный) - разные клиенты могут одновременно вызвать удаленный модуль данных из нескольких потоков, при этом модель COM следит, чтобы не было конфликта вызовов. Однако может возникнуть конфликт потоков, который отслеживается только в версии COM+. При отсутствии этой версии нужно использовать модель Apartment.
  • В этом поле оставляем модель по умолчанию Apartment.

    Поясним материал на схеме:

    (рис 28.4 ) Поведение сервера в зависимости от способа создания экземпляров

    Нажмите кнопку "ОК", окно Мастера создания удаленного модуля закроется, и у нас появится модуль данных MyRDM. Сохраните его на диск под именем RDM.

    В этот контейнер с вкладки ADO поместите компонент ADOConnection и две таблицы ADOTable. Щелкните дважды по ADOConnection, чтобы открыть редактор подключений. Нажмите кнопку Build, чтобы открылся список поставщиков данных. Здесь выберем " Microsoft Jet 4.0 OLE DB Provider " и нажмем копку "Далее". В следующем окне, в поле 1 поместим адрес и имя файла (вы уже поместили файл по этому адресу?):

    C:\DataBases\ok.mdb

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

    Далее нажимаем "ОК" и закрываем редактор подключений. Свойство LoginPrompt компонента переведем в False, чтобы при подключении не выходило запроса на имя пользователя и пароль. А свойство Connected переведем в True, чтобы физически подключить компонент к базе данных.

    Займемся табличными компонентами. В обеих ADOTable в свойстве Connection выберите наш ADOConnection1. У первой таблицы в свойстве TableName выберите таблицу LichData, а свойство Name переименуйте в TLichData. У второй таблицы в свойстве TableName выберите таблицу Telephones, а свойство Name переименуйте в TTelephones. Свойство Active обеих таблиц переведите в True, чтобы открыть эти наборы данных. Как видите, пока что подключение сервера к базе данных мало отличается от того, что мы проходили во второй лекции, при разработке локальной базы данных для отдела кадров. Однако дальше начинаются различия.

    Как вы помните, посредником между НД и компонентами отображения данных является компонент DataSource. Однако в серверном приложении у нас нет компонентов отображения данных, поэтому компоненты DataSource для этого нам не нужны. Однако нам нужно будет организовать связь таблиц один-ко-многим, а для этого один DataSource нам все-таки понадобится.

    Также нам понадобится посредник для связи с клиентским приложением, и этим посредником является компонент DataSetProvider, который находится на вкладке Data Access Палитры компонентов. Такой компонент требуется устанавливать к каждому набору данных ( Table или Query ), с которым будет соединяться клиентское приложение. Установите в контейнер MyRDM два таких компонента. У первого свойство Name переименуйте в DSPLichData, а в свойстве DataSet выберите таблицу TLichData. У второго свойство Name переименуйте в DSPTelephones, а в свойстве DataSet выберите таблицу TTelephones.

    Теперь установим связь главная-подчиненная между таблицами, для этого установите один компонент DataSource. Его свойство Name переименуйте в dsLichData, а в свойстве DataSet выберите таблицу TLichData. Организация связи производится в таблице TTelephones. В ее свойстве MasterSource выберите dsLichData, затем раскройте сложное свойство MasterFields. Откроется окно редактора связи:

    (рис 28.5 ) Редактор связей

    В разделе подчиненного поля выберите "Сотрудник", в разделе главного поля - "Ключ", нажмите кнопку Add, чтобы создать связь, и кнопку OK, чтобы подтвердить это. Внешний вид полученного контейнера представлен на рисунке ниже:

    (рис 28.6) Удаленный модуль данных

    Это все, сервер приложений готов. Как видите, даже не пришлось подключать удаленный модуль данных к главной форме командой File -> Use Unit. Сохраните проект и командой Run -> Run (или кнопкой Run на панели инструментов) скомпилируйте и загрузите полученную программу. При этом произошли две вещи: проект скомпилировался в выполняемую программу, а при первом запуске наш сервер зарегистрировался в реестре Windows. Теперь Windows знает, где находится наш сервер, и при необходимости сможет его автоматически загрузить.

    К слову сказать, при переносе серверного файла на другой ПК нет необходимости даже загружать эту программу, чтобы прописать ее в реестре Windows, достаточно из командной строки загрузить ее с параметром / regserver, при этом программа лишь пропишется в реестре и сразу отключится. А для удаления регистрации этого сервера из реестра нужно загрузить его с параметром / unregserver, например, так (у вас может быть другой адрес):

    C:\ MyNewServer\ MyNewServer.exe /unregserver

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

    Как уже упоминалось, для правильной работы серверов DCOM на серверном ПК должна быть установлена и зарегистрирована библиотека midas.dll. В нашем случае этого делать не нужно, так как при установке Delphi библиотека устанавливается и регистрируется автоматически. Однако если вы будете использовать созданный сервер приложений на другом ПК, где не устанавливалась Delphi, то зарегистрировать библиотеку придется вручную. Для этого на вашем ПК нужно найти файл библиотеки, он устанавливается по адресу (для Windows XP ):

    C:\Windows\System32

    Этот файл нужно скопировать на ПК, который вы собираетесь использовать в качестве сервера, по этому же адресу. В этой же папке находится утилита regsvr32.exe, которая предназначена для регистрации библиотек *.dll. Чтобы зарегистрировать нашу библиотеку, надо из командной строки (или в окне команды Пуск -> Выполнить) вызвать утилиту, передав ей в качестве параметра имя библиотеки:

    C:\Windows\System32\regsvr32 midas.dll

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

    C:\Windows\System32\regsvr32 /u midas.dll

    Не снимайте регистрацию на вашем ПК, иначе потом вы не сможете загрузить сервер приложений!

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

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

    Свойства компонента DataSetProvider
    Свойство Описание
    Constraints Если содержит True, клиенту пересылается информация о наложенных на данные ограничениях. Клиент имеет возможность организовать локальный контроль данных.
    DataSet Содержит имя связанного с компонентом набора данных ( TTable, TQuery, TStoredProc )
    Exported При значении True клиент имеет возможность использовать интерфейс IAppServer при обращении к провайдеру.
    Options Сложное раскрывающееся свойство. Определяет, какие данные будут включены в передаваемый клиенту пакет. Подробнее о параметрах этого свойства смотрите следующую таблицу.
    ResolveToDataSet Определяет, как обновляются данные. Если содержит True - то в НД, указанном в свойстве DataSet. Иначе - непосредственно в серверной БД.
    UpdateMode Определяет критерии поиска записи в наборе данных при сохранении изменений этой записи клиентом. Если значение upWhereAll, поиск записи ведется по всем полям; если upWhereChanged - по ключевым и измененным полям; если upWhereKeyOnly - только по ключевым полям.

    Параметры свойства Options компонента DataSetProvider
    Параметр Описание
    poFetchBlobsOnDemand По умолчанию, данные из BLOB полей клиенту не пересылаются, чтобы излишне не загружать трафик. Если свойство содержит True - данные пересылаются. Иначе, эта возможность отключена, и чтобы получить BLOB -данные записи, клиентское приложение должно явно использовать метод FetchBlobs.
    poFetchDetailsOnDemand Данные из вложенных или подчиненных таблиц не включаются в пакет. Чтобы их получить, клиентское приложение использует метод FetchDetails. Если свойство имеет значение True, то эти данные включаются в пакет автоматически.
    poIncFieldProps В пакет включаются такие свойства полей, как Alignment, DisplayLabel, DisplayWidth, Visible, DisplayFormat, EditFormat, MaxValue, MinValue, Currency, EditMask, DisplayValues.
    poCascadeDeletes Дает серверу распоряжение автоматически удалять каскадным методом записи из подчиненных таблиц, если пользователь удалил связанную с ними запись в главной таблице.
    poCascadeUpdates Дает серверу распоряжение автоматически изменять каскадным методом записи из подчиненных таблиц, если пользователь изменил связанную с ними запись в главной таблице.
    poReadOnly Данные клиенту предоставляются только для чтения.
    poAllowMultiRecordUpdates Параметр допускает индивидуальные обновления сразу нескольких записей. Если параметр = False, множественные обновления будут автоматически прерваны.
    poDisableInserts Параметр запрещает клиенту вставку новых записей.
    poDisableEdits Параметр запрещает клиенту редактирование записей.
    poDisableDeletes Параметр запрещает клиенту удаление записей.
    poNoReset Запрещает обновление набора данных сервера перед передачей записей клиенту.
    poAutoRefresh Разрешает автоматическое обновление записей клиента при их изменении. Для ускорения работы эта опция по умолчанию отключена.
    poPropogateChanges Обновления, сделанные в событиях BeforeUpdateRecord или AfterUpdateRecord передаются клиенту в пакете, и объединяются с клиентским набором данных.
    poAllowCommandText Предоставляет клиенту возможность отменить НД, заменяя его НД, полученным SQL -запросом.
    poRetainServerOrder Запрещает клиенту изменять сортировку записей, полученную по умолчанию.

    Некоторые полезные методы компонента DataSetProvider
    Метод Описание
    ApplyUpdates Обновляет данные. Имеет параметры: Delta - измененные, новые или удаленные записи; MaxError - максимальное количество ошибок, при котором обновление прекращается (0 - не ограничено); ErrorCount - количество допущенных ошибок. Метод возвращает клиенту набор записей, при обновлении которых произошла ошибка.
    DoDelete Вызывается для каждой записи, которая должна быть удалена.
    DoInsert Вызывается для каждой новой записи.
    DoUpdate Вызывается для каждой модифицированной записи.
    EndUpdate Вызывается в момент завершения обновлений.
    LogUpdateError Добавляет ошибочную запись в журнал ошибок, который затем передается клиентскому приложению.

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

    Вернуться к учебному плану