Все ленты — последние статьи

ISAPI, MySQL и DataSnap XE2. http://www.webdelphi.ru

 

 

Сегодня картинок тоже будет не мало. В продолжение темы «Windows 7 x64, IIS, ISAPI и DataSnap XE2 в картинках» решил я поработать с базой данных. Получать от сервера ReverseString, конечно, весело («Оно работает!», «Уау!» и всё такое прочее), но на деле врядли кому-то такой сервер пригодиться. Поэтому решил расширить свой кругозор и доработать уже имеющийся ISAPI-модуль и клиента, чтобы они смогли обмениваться данными — сервер будет читать данные из базы данных и отправлять их клиенту. Клиент, в свою очередь, будет получать данные с сервера, работать с ними и отправлять изменения на сервер.

 

Вообще, т.к. наш ISAPI-модуль предназначен для IIS, то, наверное, логичнее было бы рассказать про работу c MSSQL, а не с MySQL. Но, признаюсь, попытка установки MSSQL Server на мой компьютер была неудачной по причине того, что меня просто откровенно задолбало выкачивать с сайта Microsoft тучу каких-то сервис-паков к дистрибутиву, которые в итоге просили ещё не меньшую кучу обновлений. В общем плюнул я на это дело и решил установить MySQL — всё-таки это очень популярная СУБД, да и провайдеры, предоставляющие Win-хостинг обычно дают доступ и к MSSQL и к MySQL (например, МастерХост). Да и, в принципе, какая нам сегодня разница, что за СУБД будет использоваться MSSQL, MySQL или вообще FireBird? Основная задаче сегодня — «научить» сервер и клиент работать с данными из базы, а её (БД) тип — дело второе.

Содержание

  1. Установка и настройка необходимого ПО
  2. Настраиваем сервер на работу с MySQL
    1. «DBX Error:  Driver could not be properly initialized…» Как победить?
    2. Создаем соединение с БД, читаем данные и отправляем их клиенту
  3. Разработка клиента
    1. Создаем клиент для чтения данных
    2. Создаем клиент для чтения и редактирования данных
  4. Отладка ISAPI-модулей в Delphi

Установка и настройка необходимого ПО

Итак, начнем с установки необходимого программного обеспечения и его настройки. Для сегодняшней работы скачал у установил следующее ПО:

  1. MySQL 5.0 с сайта mysql.ru
  2. Для работы с базами данных был скачан с mysql.com и установлен MySQL Workbanch

По умолчанию MySQL установится в Windows 7 x64 в директорию c:\Program Files (x86)\MySQL\MySQL Server 5.0\. В этой же директории Вам будет предложено хранить файлы БД — я при установки оставил все настройки без изменений.

Теперь подготовим нашу тестовую БД с помощью MySQL Workbench. Запускаем программу и создаем новое подключение:

 

В общем случае, настройки должны быть такими:

  • HostName = 127.0.0.1 (или localhost)
  • Port = 3306
  • User = root
  • Password = (заданный при настройке MySQL)

После того, как соединение создано, дважды кликаем по его названию в списке и создаем новую БД:

 

Я создал БД с такими настройками:

  • Name = dsbase
  • Collation = utf8 — utf8_general_ci

Проще было бы работать с кодировкой cp1251, но в Сети всё же чаще используется utf8 — с этой кодировкой и будем баловаться разбираться. Теперь остается последний шаг — создать таблицу в нашей базе. Для этого дважды щелкаем в списке БД по нашей только что созданной, чтобы она стала активной, жмем кнопку «Create New Table…» (или вызываем контекстное меню в дереве у узла Tables) и создаем в редакторе новую таблицу:

 

Я создал таблицу с названием dstable и четырьмя полями — id, имя, фамилия и день рождения. Какую таблицу создадите Вы — не важно, главное, чтобы она была в БД.

Теперь приступим к работе в Delphi. И первым делом немного переделаем наш ISAPI-модуль.

Настраиваем сервер на работу с MySQL

Когда я рассматривал работу над ISAPI-dll в прошлый раз, то выбрал для класса с серверными методами предка TComponent. Тогда мне не требовалась никакая работа с наборами данных или невизуальными компонентами, поэтому я ограничился самым простым классом из предложенных. Сегодня же нам потребуются и TSQLConnection и другие невизуальные компоненты, поэтому удобнее будет использовать другого предка, например, TDSServerModule. Удаляем старый проект сервера — в нем нет ничего, кроме того, что было создано мастером и создаем новый, как я рассказывал в прошлый раз, но только в качестве предка для класса серверных методов выбираем TDSServerModule. Теперь в менеджере проектов наш сервер будет выглядеть так:

 

Пока ServerMethodUnit1 ничего не содержит и сейчас мы это исправим. Первым делом создадим новое подключение для MySQL в Data Explorer. Настройки соединения у нас должны быть следующие:

 

  • ServerName = localhost
  • Database Name = dsbase (её мы и создавали в Workbench)
  • User Name/Password = заданным при настройке MySQL.

Проверяем соединение — соединение есть:

 

Но это оно (соединение) есть у меня. А вот у Вас его может и не быть с самого начала. Например, Вы можете получить вот такое нехорошее сообщение:

DBX Error:  Driver could not be properly initialized.  Client library may be missing, not installed properly, of the wrong version, or the driver may be missing from the system path..

Поэтому сделаем небольшое лирическое отступление и посмотрим как с такой ситуацией бороться.

«DBX Error:  Driver could not be properly initialized…» Как победить?

Во-первых, надо проверить наличие библиотеки libmysl.dll на компьютере. Эта библиотека должна располагаться либо в директории с проектом, либо в следующих местах:

Для x86 Для x64
 $BDS\bin\ $BDS\bin64\
 Windows\System32 Windows\SysWOW64\

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

Библиотека для MySQL 5(914.01 kB)

Скачиваете архив, распаковываете DLL, например, в Windows\System32 и соединение заработает. Ну, а если не заработает…делитесь решениями в комментариях.

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

Создаем соединение с БД, читаем данные и отправляем их клиенту

Открываем модуль с серверными методами (по умолчанию — это ServerMethodsUnit1) и бросаем на него сначала такие компоненты:

  • TSQLConnection
  • TSQLDataSet

 

Для TSQLConnection устанавливаем следующие свойства:

  • ConnectionName = dsMySQL (заданное в Data Explorer)
  • Driver = MySQL
  • VendorLib = LIBMYSQL.dll
  • Connected = True

У TSQLDataSet в свойстве SQLConnection выбираем SQLConnection1, а также сразу зададим и свойство CommandText. Для этого вызовем редактор и составим SQL-запрос вида:

SELECT * FROM dstable

 

Теперь можете проверить, что в SQLDataSet поступают данный — переключите свойство Active в значение True — при этом, если всё было сделано верно,  не должно вызываться никаких исключений.

Теперь разберемся с тем как переслать клиенту все, что было получено из БД. Клиент не в курсе, что там делает на другой стороне наш сервер, как и куда подключается, что считывает. Клиенту главное — получить набор данных в каком-либо удобоваримом для него виде. И для этого мы напишем очень просто серверный метод, который будет возвращать клиенты TDataSet. Открываем исходный код модуля с серверным классом и создаем такой метод:

type TServerMethods1 = class(TDSServerModule) //.....// private { Private declarations } public { Public declarations } //......// function GetDataSet: TDataSet; end;   function TServerMethods1.GetDataSet: TDataSet; begin SQLDataSet1.Open; Result:=SQLDataSet1; end;

Всё. Большего нам пока от сервера и не требуется. Как только клиент вызовет метод GetDataSet наш SQLDataSet1 получить все данные из таблицы и отправиться прямиком на клиент. Теперь вернемся к разработке клиента.

Разработка клиента

Клиент может только получать данные от сервера, а может (что чаще всего происходит) получать, добавлять и редактировать данные на сервере. В зависимости от того в каком режиме будет работать клиент (Read Only или Read/Write) будет зависеть состав компонентов. Рассмотрим оба варианта работы клиента начнем с более простого.

Создаем клиент для чтения данных

Создаем новый проект Delphi и бросам на главную форму следующие компоненты:

  1. TSQLConnection
  2. TSqlServerMethod
  3. TDataSetProvider
  4. TClientDataSet
  5. TDataSource
  6. TDBGrid
  7. TDBNavigator
  8. TCheckBox

У Вас должно получиться что-то типа такого:

Теперь настроим компоненты. Про настройку TSQLConnection я рассказывал в прошлый раз, поэтому можете открыть ссылочку и прямо по картинкам провести настройку компонента. Единственное, что следует помнить, что ISAPI-модуль (наш сервер) должен работать, чтобы Вы смогли сгенерировать клиентский модуль с серверными методами.

Вообще одним из различий ISAPI-модуля от CGI является то, что будучи один раз вызванным ISAPI-модуль не выгружается из памяти сервера пока тот не будет перезагружен, поэтому убедитесь, что Ваш IIS работает, а DLL сервера лежит по заданному пути (просто задайте в браузуру путь к ней и посмотрите на вывод тестовой строки «DataSnap Server»)

Теперь настроим TSQLServerMethod. Вообще, этот компонент удобно использовать в том случае, если нам необходимо получить данные только для чтения. У TSQLServerMethod устанавливаем следующие свойства:

  1. SQLConnection = SQLConnection1;
  2. ServerMethodName = TServerMethods1.GetDataSet;

Можете проверить работу компонента — переключите свойство Active в True — если соединение работает корректно, то это действие приведет к тому, что свойство TSQLConnection.Connected также станет равным True.

У компонента TDataSetProvider в свойстве DataSet указываем SQLServerMethod1.

У ClientDataSet1 в свойстве ProviderName указываем DataSetProvider1.

У DataSource1 в свойстве DataSet указываем ClientDataSet1

У DBGrid1 в свойстве DataSource указываем DataSource1

У DBNavigator1 в свойстве DataSource указываем DataSource1

И, наконец, у CheckBox1 пишем обработчик OnClick:

procedure TForm19.CheckBox1Click(Sender: TObject); begin ClientDataSet1.Active:=CheckBox1.Checked; end;

И всё. Клиент для чтения данных с сервера готов к работе. Для порядка можете из DBNavigator1 исключить кнопки, связанные с модификацией данных, а можете и не убирать, если они вам не мешают. Чтобы убедиться, что все работает как часы — просто измените свойство Active у ClientDataSet1 на True и табличка DBGrid должна вывести вам все данные из БД, но т.к. я ещё не вносил никаких данных, то у меня вид окна программы стал таким:

 

В приведенном выше примере клиента мы создали вот такую связь компонентов:

 

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

Создаем клиент для чтения и редактирования данных

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

  1. TSQLConnection
  2. TDSProviderConnection
  3. TClientDataSet
  4. TDataSource
  5. TDBGrid
  6. TDBNavigator
  7. TCheckBox

Внешний вид главной формы приложения у меня получился следующий:

 

Как видите, состав компонентов стал несколько другим. TDSProviderConnection необходим нам для того, чтобы обеспечить ссылку на TDataSetProvider на стороне сервера. Но, как Вы можете Видеть выше — никакого TDataSetProvider у нашего сервера нет. Поэтому на минуту вернемся к серверу, добавим в модуль ServerMethodsUnit1 компонент TDataSetProvider у которого в свойстве DataSet укажем SQLDataSet. Вид модуля у сервера теперь стал таким:

 

Теперь пересобирите ISAPI-модуль, выключите IIS, забросьте куда необходимо IIS-модуль и снова включите IIS.

Если сервер не будет работать, то мы просто не сможем получить ссылку на серверный DataSetProvider в клиенте.

 Возвращаемся к нашему клиенту. Будем считать, что TSQLConnection у Вас уже настроен (тритий раз повторяться не буду). Переходим сразу к TDSProviderConnection и устанавливаем у него следующие свойства:

  1. SQLConnection = SQLConnection1
  2. ServerClassName = TServerMethods1
Здесь будьте предельно внимательны — не перепутайте класс TServerMethods1Client, который находится в клиенте с классом TServerMethods1, который находится в модуле сервера.  TDSProviderConnection  должен содержать имя класса именно сервера. По хорошему, было бы не плохо, если бы свойство ServerClassName содержало список, как у TSQLServerMethod, но имеем пока то, что имеем.

Теперь устанавливаем свойства у TClientDataSet:

  1. RemoteServer = DSProviderConnection1
  2. ProviderName = DataSetProvider1;

Свойство ProviderName — это список, который формируется после запроса к серверу и в это список ничего руками вписывать не следует. Если у вас не получается зделать вот так:

 

то одно из двух:

  1. Сервер не работает
  2. Не правильно настроен TDSProviderConnection или TSQLConnection

Теперь устанавливаем у DataSourse свойство DataSet как ClientDataSet1 и настраиваем свойства у DBGrid и DBNavigator.

У CheckBox1 снова пишем обработчик OnClick:

procedure TForm18.CheckBox1Click(Sender: TObject); begin ClientDataSet1.Active:=CheckBox1.Checked; end;

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

procedure TForm18.Button1Click(Sender: TObject); begin ClientDataSet1.ApplyUpdates(0); end;

Вот теперь можно запустить наш клиент и попробовать добавить/отредактировать/удалить записи.

Будьте уверены — данные отправятся на сервер и сохраняться в базе данных.

Если вместо русских символов в таблице появляются ??????????? то установите на сервере свойство TConnection.Driver.ServerCharSet=»utf8″

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

Отладка ISAPI-модулей в Delphi

Как Вы знаете, любую dll-ку в Delphi можно отладить, если в свойствах проекта прописать значение «Host Application». Указываем в свойстве exe-шник, который использует нашу dll, запускаем проект и спокойненько отлаживаем библиотеку. Чем тогда отличается ISAPI-модуль от обычной DLL? Ответ очевиден — ничем. Это точно такая же динамическая библиотека, экспортирующая методы и для её отладки нам просто необходимо найти нужный exe-файлик.

Немного покопавшись по Сети я нашел тот самый exe-файл:

C:\Windows\System32\inetsrv\w3wp.exe

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

Свойства проекта, который мы будем отлаживать должны быть такими:

  • Host Application = C:\Windows\System32\inetsrv\w3wp.exe
  • Parameters = -debug
Если у вас ISS несколько сайтов и требуется отладить модуль, которой лежит на сайте, скажем с ID=10, тогда строка Parameters должна быть такой
  • Host Application = C:\Windows\System32\inetsrv\w3wp.exe
  • Parameters = -debug -s 10

Чтобы отладить ISAPI-dll выполняем следующие действия:

  1. Останавливаем полностью работу IIS
  2. Ставим где надо точки останова
  3. Запускаем проект dll и убеждаемся, что процесс w3wp.exe стартовал:

 

4. Запускаем клиента, что-нибудь делаем и убеждаемся, что отладка проходит отлично:

 

Если отладка вдруг не работает — убедитесь, что скомпилированная dll сохраняется в той директории из которой она стартует при работе сайте.

На сегодня все. Осталось выложить разработанные в рамках статьи проекты — их Вы всегда сможете скачать со страницы «Исходники«.