Свобода движения. Жить танцуя!

Posted by on in Blogs

Фраза в заголовке взята из другой темы, но именно это ощущение возникает, когда узнаешь, как быстро и без усилий можно перемещать данные с помощью технологий, заложенных в FireDAC! 

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

Потребовалось решить простую задачу - подготовленные заранее строки для справочника необходимо загрузить в рабочую базу данных. Одна "закавыка" - "рабочей" базой в одном проекте является  коллекция в MongoDB, в другом - БД InterBase XE7, утилиты которого не слишком удобны для работы с данными в формате CSV (данные с разделителями - запятыми).

Откроем Delphi, и создадим новый VCL-проект:  File->New->VCL forms Application-Delphi

На форму положим компонент TFDBatchMoveTextReader, который будет считывать данные из внешнего файла, и компонент TFDBatchMoveDataSetWriter, который будет записывать эти данные в DataSet. Добавим в качестве Dataset-а компонент TFDMongoQuery, чтобы записать данные в БД MongoDB. Чтобы связать Dataset с нужной базой данных, добавим компонент TFDConnection, который будет управлять коннекцией с рабочим сервером СУБД.

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

Так как исходные данные содержатся в текстовом файле на диске, мы выбрали компонент TFDBatchMoveTextReader. На самом деле, имеется несколько разных компонент-ридеров для различных типов источников исходных данных. Укажем имя и путь с файлу с исходными данными. В моем случае это был файл из прошедшего воркшопа по контрольным спискам и содержал справочник пунктов-вопросов одной из использовавшихся анкет. С помощью Object Inspector установим значение свойства FDBatchMoveTextReader1.FileName компонента равным 'C:\data\Table - CLITEMS.csv', а свойства Encoding равным ecUTF8, так как мы хотим хранить в базе данных вопросы на русском языке.  В группе свойств DataDef можно уточнить все детали формата исходного файла. Мне требуется только указать значение DataDef.Separator равное , (запятая). Если бы файл содержал поля дат или времени, в FormatSettings можно указать их реальный формат, чтобы при чтении дата и время воспринимались корректно. 

Считанные ридером данные будут помещаться в нужный Datatset соответствующим компонентом-writer. Кстати, также имеется несколько разных компонент-writer для различных форм приемников информации. Мы собирались передавать данные в FDMongoQuery1, укажем его в свойстве DataSet нашего FDBatchMoveDataSetWriter1. Остальные его свойства годятся и так.

Чтобы данные сразу записывались на сервер MongoDB, нужно настроить FDConnection1. Самый простой способ - это вызвать Connection Editor, выбрав из меню после нажатия правой кнопки мыши на FDConnection1. Укажем Driver ID: Mongo, это  автоматически добавит на форму FDPhysMongoDriverLink1. Я также указал имя базы данных: test, Server: localhost, Port: 27017, как это установлено по умолчанию. Кнопка Тест очень полезна, чтобы проверить работоспособность настроек соединения с сервером БД. Осталось только указать имя коллекции, куда будут загружаться данные. Для этого в Object Inspector для FDMongoQuery1 установите значения свойств DatabaseName: test и CollectionName: CLItems.

За управление считыванием исходных данных ридером, преобразованием и записью их в Dataset отвечает компонент TFDBatchMove, который также надо добавить на форму. У него надо указать имена наших объектов Reader и Writer (FDBatchMoveTextReader1 и FDBatchMoveDataSetWriter1, соответственно), а также в свойстве Analyze отметить taDelimSep - для обработки разделителей полей, taHeader - у нас в первой строке файла - имена колонок, taFields. При желании, можно еще указать файл, куда будет записываться журнал хода загрузки LogFileName: Dataproc.log. Я также оставил в свойстве Mode значение по умолчанию, поскольку требуется только загрузка новых записей.

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

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

procedure TForm1.Button1Click(Sender: TObject);
begin
  FDBatchMove1.Execute;
end;

 

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

И это еще не все! Вы можете начать импорт прямо в Design-time, без компиляции и запуска бинарного модуля - нажмите правую кнопку мыши на FDBatchMove1 и в всплывшем меню выберите Execute. Там же можно попросить компонент попробовать разобрать формат реального файла и убедиться, что все считывается корректно. А с помощью свойства Mappings можно устанавливать соответствие между полями исходного текстового файла и имеющимися колонками в БД.

В моем примере мы загружали данные с разделителями в коллекцию СУБД MOngoDB, которая не является реляционной. Что требуется, чтобы перенастроить этот пример для загрузки в реляционную СУБД, например InterBase? Вместо TFDMongoQuery нужно использовать любой другой компонент, реализующий интерфейс TDataSet, например TFDQuery или TFDTable, а в качестве драйвера FDConnection указывать IB с соответствующими параметрами соединения. Все остальное сделает FDBatchMove, причем достаточно оптимальным образом. Хотя мы выполнили все настройки в визуальном режиме, все то же самое можно сделать динамически в коде программы.

С помощью TFDBatchMove и его связанных компонент написание программ, реализующих ETL-задачи становится таким простым и приятным, что повышает настроение! Надо будет внести предложение использовать программирование ETL-программ в Delphi в качестве лечебного средства от депрессии. :)

 



About
Gold User, Rank: 11, Points: 295
SC at Embarcadero. DB Tools expert Delphi practitioner

Comments

Check out more tips and tricks in this development video: