Продолжаем работать с FireDAC. В данной статье попробуем установить private соединение с БД динамически и дать возможность изменять параметры на ходу. Вот какая программа у нас получится.
В левой части у нас Memo, которое отражает параметры ConnectionDefs. О том, что такое ConnectionDefs, я писал в предыдущем посте. Можно эти параметры редактировать и нажимать на SaveParams, для того, чтобы изменения параметров затронули соответствующее определение соединения – ConnectionDef.
Мы научимся создавать Private соединение динамически и изменять его параметры также динамически. И в принципе, разберемся с основными моментами по PrivateConnection в FireDAC.
Начали!
Создадим VCL приложение
Файл FDDrivers.ini
Найдем файл FDDrivers.ini в следующей директории
1 |
C:\Users\Public\Documents\Embarcadero\Studio\FireDAC\FDDrivers.ini |
Откомпилируем наш проект и рядом с EXE файлом положим файл FDDrivers.ini
Откроем файл FDDrivers.ini и напишем в нём следующее
Это описание нашего драйвера и путь к нему, соответственно, у себя пропишите свои данные. Обратите внимание, я подписал [MySQL23], можно было и [MySQL24] и [AnyName], суть здесь в том, что это так называемый “виртуальный драйвер” – удобно, например, когда у нас драйвера для 32 битной системы и 64 битной, можно например подписать [MySQL_32bit], а другой сделать [MySQL_64bit].
Примечание
Можно и в любое другое место положить этот файл, но тогда нужно будет явно указать в компоненте FDManager, где этот файл лежит вот таким образом
1 2 |
FDManager1.DriverDefFileName:='Some path to FDDrivers.ini'; FDManager1.DriverDefFileAutoLoad:=true; |
Файл FDConnectionDefs.ini
В данном случае не нужен, так как все определения каждый раз создаются и хранятся в памяти.
Но, на всякий случай, по умолчанию его можно найти вот здесь…
1 |
C:\Users\Public\Documents\Embarcadero\Studio\FireDAC\FDConnectionDefs.ini |
Но он нам не нужен для Private соединения. Он используется для Persistent и хранит данные на подключение в открытом виде, что в теории – уязвимо и подходит, на мой взгляд для серверных программ.
В секции uses
Первоначальное состояние
1 2 3 |
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; |
Но для создания FDConnection, FDManager, FD,FDPhysMySQLDriverLink нам нужны соответствующие юниты – их легко можно получить – добавив их для начала визуально на форму, а потом удалив, в результате, раздел uses получается таким…
Примечание
FDPhysMySQLDriverLink мы нигде не используем в данной программе, в принципе этот компонент можно удалить из программы. Но это запасной способ – показать библиотеке FireDAC, где у нас находится файл mysqllib.dll, если им пользоваться, нужно прописать в свойстве VendorLib – путь до библиотеки, например так….
1 |
FDPhysMySQLDriverLink1.VendorLib:='C:\MySQLDriver\libmysql.dll'; |
Нужное состояние uses
1 2 3 4 5 6 |
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.VCLUI.Wait, Data.DB, FireDAC.Comp.Client,System.IOUtils, FireDAC.Phys.MySQLDef, FireDAC.Phys.MySQL, Vcl.ComCtrls; |
Примечание
Также, обратите внимание, я добавил сюда модуль System.IOUtils, который можно использовать для универсального задания путей через TPath, например так…
1 2 3 |
Path_FDDrivers:=TPath.GetDirectoryName(Application.ExeName)+ TPath.DirectorySeparatorChar+ 'FDDrivers1.ini'; |
Но этот код я не буду использовать так как мы изначально положили FDDrivers.ini рядом c EXE, и, судя по тому, что программа работает, FireDAC сам находит этот файл. В реальном же проекте да, наверное стоит перестраховаться и прописать путь до файла напрямую как это я показал выше.
Глобальные переменные
1 2 3 4 5 |
var Form1: TForm1; FDConnection1:TFDConnection; //<<Добавим FDManager1:TFDManager; //<<Добавим FDPhysMySQLDriverLink1: TFDPhysMySQLDriverLink; //<<Добавим |
Вспомогательные функции и процедуры
Проверка на существование определения соединения ConnectionDef
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function TForm1.IsConnectionDef(AName:string):boolean; //Вспомогательная функция определения существования ConnectionDef var i:integer; SL:TStringlist; begin SL:=TStringList.Create; //Загоняем все имена Connection Defs в SL for i := 0 to FDManager1.ConnectionDefs.Count-1 do SL.Add(FDManager1.ConnectionDefs.Items[i].Name); //Ищем AName в SL, проверем существование if Sl.IndexOf(AName)<>-1 then result:=true // Найдено else Result:=false; // Не найдено SL.Free; end; |
Создание своего определения соединения
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
procedure TForm1.CreateMyConnDefName(Sender: TObject); var oParams:TStrings; DriverID:string; begin // Если уже создано - выходим if IsConnectionDef('MyConnDefName')=true then exit; // Определяем название драйвера DriverID:='MySQL23'; //Создание переменной oParams := TStringList.Create; oParams.Add('DriverID='+DriverID); oParams.Add('DataBase=aphina_db'); oParams.Add('Password=masterkey'); oParams.Add('User_Name=root'); oParams.Add('Port=3306'); oParams.Add('Server=localhost'); // Cоздание и добавление нового ConnectionDef FDManager1.AddConnectionDef('MyConnDefName',DriverID , oParams); //Освобождение переменной oParams.Free; end; |
Обновление списка определений соединения в Combobox
1 2 3 4 5 6 7 8 9 10 |
procedure TForm1.UpdateComboBox; var i:integer; begin ComboBoxEx1.Items.Clear; for i := 0 to FDManager1.ConnectionDefs.Count-1 do ComboBoxEx1.Items.Add(FDManager1.ConnectionDefs.Items[i].Name); ComboBoxEx1.ItemIndex:=ComboBoxEx1.Items.Count-1; end; |
Отображение параметров в memo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
procedure TForm1.ShowParamsInMemo(Sender: TObject); var i:Integer; ConnDefName:string; begin ConnDefName:=ComboBoxEx1.Items[ComboBoxEx1.ItemIndex]; if IsConnectionDef(ConnDefName) then begin memo1.Lines.Clear; for i := 0 to FDManager1.ConnectionDefs.FindDefinition(ConnDefName).Params.Count-1 do memo1.Lines.Add(FDManager1.ConnectionDefs.FindDefinition(ConnDefName).Params[i]) end else memo1.Lines.Clear; end; |
Основная часть программы
FormCreate
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
procedure TForm1.FormCreate(Sender: TObject); var i:integer; begin //Создание компонентов FDConnection1:=TFDConnection.Create(Self); FDManager1:=TFDManager.Create(Self); FDPhysMySQLDriverLink1:=TFDPhysMySQLDriverLink.Create(Self); //Создание своего определения соединения Self.CreateMyConnDefName(Self); UpdateComboBox; Self.ShowParamsInMemo(Self); lConnected.Caption:='Disconnected'; end; |
Удалением компонент я нигде на занимался, возможно зря. Но, насколько я знаю, если мы пишем владельца компонента, то вместе с уничтожением владельца – уничтожаются и все его “дети”. Поэтому, теоретически удаление компонентов должно произойти в момент закрытия формы.
Кнопка Connect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
procedure TForm1.bConnectClick(Sender: TObject); begin //В этом месте назначаем соединению - определение соединения FDConnection1.ConnectionDefName:=ComboBoxEx1.Items[ComboBoxEx1.ItemIndex]; FDConnection1.Connected:=true; if FDConnection1.Connected then begin lConnected.Caption:='Connected'; end; end; |
Кнопка Disconnect
1 2 3 4 5 6 |
procedure TForm1.bDisconnectClick(Sender: TObject); begin // Отключение соединения FDConnection1.Connected:=false; if not FDConnection1.Connected then lConnected.Caption:='Disconnected'; end; |
Кнопка SaveParams
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
procedure TForm1.bSaveParams(Sender: TObject); var ConnectionDefName:string; begin //Записываем имя выбранного ConnectionDef ConnectionDefName:=ComboBoxEx1.Items[ComboBoxEx1.ItemIndex]; // Отключение соединения FDConnection1.Connected:=false; if not FDConnection1.Connected then lConnected.Caption:='Disconnected'; if IsConnectionDef(ConnectionDefName)<>false then begin // Ставим новые параметры, показываем FDManager1.ConnectionDefs.FindDefinition(ConnectionDefName).Params.Assign( memo1.Lines ); //Отражаем их обратно в Memo ShowParamsInMemo(Self); showmessage('Новые параметры успешно сохранены'); end; |
Тестируем программу
Соединяемся
Разъединяемся
Изменяем параметры
Ну и естественно получаем сообщение об ошибке при соединении с неправильным логином.