Opracował: Tomasz Neumann netom@am.gdynia.pl Technologia dbexpress w środowisku DELPHI
Technologia dbexpress DbExpress jest technologią zaproponowaną przez firmę Borland. Innowacją tego rozwiązania jest fakt, że jest to technologia międzyplatformowa, można zatem w środowisku Delphi tworzyć aplikacje zgodne z Kyliksem. Sposób jej implementacji zapewnie również pełną rozszerzalność możliwe jest dodawanie możliwości korzystania z nowych typów baz danych poprzez dołączanie odpowiednich sterowników. Każdy z takich sterowników implementuje zestaw nowych interfejsów umożliwiających dostęp do danych specyficznych dla danego typu serwera. Jedną z najważniejszych cech architektury dbexpress jest jednokierunkowy charakter jej zbioru danych. Niemożliwe jest zatem używanie metod Last oraz Prior klasy TDataSet. Wśród dostępnych metod eksploracji danych w tabeli możliwe jest tylko używanie metod First oraz Next. Kolejnym ograniczeniem jest niemożliwość bezpośredniej modyfikacji rekordów. Komponenty dbexpress Zadaniem komponent TSQLConnection jest zapewnienie zestawienia połączenia pomiędzy serwerem baz danych a innymi komponentami wchodzącymi w skład dbexpress. Parametry pracy komponentu TSQLConnection zapisane są w dwóch plikach konfiguracyjnych dbxdrivers.ini oraz dbxconnections.ini. (C:\Program Files\Borland\BDS\4.0\) Plik Opis dbxdrivers.ini zawiera listę wszystkich obsługiwanych przez dbexpress sterowników wraz z ustawieniami dotyczącymi tychże sterowników. dbxconnections.ini zawiera listę połączeń nazwanych, będących odpowiednikami aliasów DBE WAŻNE!!! Biblioteki z których korzysta środowisko Delphi są ściśle przypisane do wersji bazy danych. Może zdarzyć się tak, że część bibliotek należy podmienić/dodać. Nawiązanie połączenia Aby ustanowić połączenie z serwerem baz danych należy umieścić na formie komponent TSQLConnection oraz ustawić właściwość ConnectionName. Na rozwijanej liście pojawią się wszystkie te nazwane połączenia, które zostały dodane do pliku konfiguracyjnego dbxconnections.ini. Na rysunku obok przedstawiono parametry zestawienia połączenia z serwerem MySQL. Po ustawieniu właściwości ConnectionName zostały zgodnie z plikiem konfiguracyjnym właściwości dodatkowe, takie jak: DriverName, GetDriveFunc, LibraryName oraz VendorLib. Istotnym parametrem jest właściwość LoginPrompt, domyślnie ustawiona na True. Pomimo określenia w pozostałych parametrach nazwy użytkownika oraz hasło wymaganych przy zestawianiu połączenia, aplikacja zawsze będzie pytała się o nie jeszcze raz.
Właściwości Connected odpowiada za inicjację oraz zerwanie połączenia z serwerem baz danych. Szczegółowe parametry połączenia zapisuje się we właściwości Params. Proces edycji odbywa się w osobnym oknie (rysunek) Istotnymi parametrami połączenia są właściwości HostName, czyli nazwa domenowa lub adres IP hosta z uruchomioną usługą baz danych. Właściwości User_Name oraz Password odpowiadają za określenie praw dostępu do baz danych znajdujących się na serwerze. Właściwość Database ustawia domyślną bazę danych. Zestawienie przedstawionych właściwości może różnić się dla różnych systemów baz danych. W przypadku pracy z wieloma różnymi systemami baz danych możliwe jest zapisywanie wszelkich ustawień pliku połączeń nazwanych. Edycja pliku możliwa jest poprzez dwukrotne kliknięcia komponentu klasy TSQLConnection. Kolejnym komponentem korzystającym z zestawionego połączenia przez komponent TSQLConnection jest TSQLDataSet. Komponent ten reprezentuje jednokierunkowy zbiór danych zawierający dane pochodzące z serwera. Rodzaj danych zależy od właściwości CommandType. Z listy rozwijanej tej właściwości można wybrać ctquery, ctstoredproc oraz cttable. Dla każdej z opcji we właściwości ComandText należy podać odpowiednio zapytanie SQL, nazwę procedury składowanej lub nazwę tabeli. Istotnym parametrem jest właściwość SchemaName w której jeszcze raz należy podać nazwę bazy danych, na której chcemy wykonać operacje. We właściwości SQLConnection wybiera się nazwę komponentu odpowiadającego za połączenie z serwerem baz danych. Po zmianie właściwości Acive na wartość True w aplikacji z komponentem TSQLDataSet z parametrami jak na rysunku obok komponent będzie zawierał tabelę kraj ze wszystkimi jej rekordami. Ustawienie wszystkich właściwości możliwe jest w czasie projektowania aplikacji jak również z poziomu kodu programu. Przedstawia to przykład poniżej.
1 procedure TForm1.Button1Click(Sender: TObject); 2 begin 3 SQLDataSet1.Close; 4 SQLDataSet1.SchemaName := 'kraj'; 5 SQLDataSet1.CommandType := ctquery; 6 SQLDataSet1.CommandText := 'SELECT COUNT(*) AS ilosc FROM kraj'; 7 SQLDataSet1.Open; 8 Button1.Caption := SQLDataSet1.FieldByName('ilosc').AsString; 9 end; Zaprezentowany kod źródłowy powiązany jest ze zdarzeniem Click obiektu Button1 (1). Pierwszą instrukcją jest zamknięcie istniejącego zbioru danych (3). Następnie wybrana jest baza danych (4) na której chcemy wykonać zapytanie (5). Treść zapytania SQL (6) zwróci ilość krotek znajdujących się w tabeli kraj. Jeśli instrukcja języka SQL zwraca zbiór wynikowy w celu otrzymania wyniku należy wywołać metodę Open (7). Jeżeli instrukcja miałby dokonać modyfikacji krotki, tabeli lub bazy danych należy wywołać metodę ExecSQL. Kolejną instrukcją jest pobranie wartości z komponentu SQLDataSet i wyświetlenie jej na przycisku Button1 (8). Wynikiem prezentowanego pytania SQL jest tabelka z jedną kolumną o nazwie ilość oraz jednym wierszem zawierającym ilość krotek w tabeli kraj. W technologii dbexpress dostrzec można tzw. wsteczną kompatybilność. Jej objawem są komponenty takie jak TSQLTable, TSQLQuery oraz TSQLStoredProc. Funkcjonują one podobnie do ich odpowiedników z BDE z ograniczeniem wynikającym z jednokierunkowego zbioru danych. Nie oferują nic więcej, niż komponent TSQLDataSet. Dwukierunkowe zbiory danych w technologii dbexpress TSQLConnection TDataSetProvider TDataSource TSQLDataSet TClientDataSet Do tej pory technologia dbexpress wykorzystywana była jako realizacja idei jednokierunkowego, niemodyfikowalnego zbioru danych. Komponentem, za pomocą którego możliwe jest zarówno dwukierunkowa nawigacja po zbiorze danych jak i modyfikowanie danych na serwerze jest komponent TSQLClientDataSet. Schemat powiązań dwukierunkowej obsługi bazy danych. SQLConnection1 zestawienie połączenia SQLDataSet1.SQLConnection := SQLConnection1; DataSetProvider1.DataSet := SQLDataSet1; ClientDataSet1.ProviderName := DataSetProvider1; DataSource1.DataSet := ClientDataSet1; DBGrid1.DataSource := DataSource1.
W aplikacjach wykorzystujących dwukierunkową nawigację po zbiorze danych jest komponent TClientDataSet. Dostarczone są do niego wszystkie dane, które są wynikiem zapytania i znajdują się w komponencie TSQLDataSet. Elementem pośredniczącym w przekazywaniu danych jest komponent TDataSetProvider. procedure TForm1.Button4Click(Sender: TObject); begin SQLDataSet1.Close; SQLDataSet1.SchemaName := 'kraj'; SQLDataSet1.CommandType := ctquery; SQLDataSet1.CommandText := 'SELECT * FROM kraj'; SQLDataSet1.Open; ClientDataSet1.Open; ClientDataSet1.Last; ClientDataSet1.Prior; ClientDataSet1.Edit; ClientDataSet1.FieldByName('numer').AsInteger := 456; ClientDataSet1.ApplyUpdates(0); end; Uruchomienie powyżej zamieszczonej procedury spowoduje pobranie wszystkich krotek z tabeli kraj, następnie aktualizacji przedostatniej krotki w polu numer do wartości 456 a następnie zaktualizowaniu bazy danych umieszczonej na serwerze. W zaprezentowanym kodzie istotną instrukcją jest ostatnia linia kodu. Wywołanie metody ApplyUpdates wykonuje fizyczne zmiany w bazie danych. Jeśli aplikacja automatycznie ma dbać o aktualizację danych w aplikacji klienckiej i na serwerze można wykorzystać zdarzenie AfterPost, które wywoływane jest przy każdej zmianie zawartości krotek komponentu ClientDataSet. procedure TForm1.ClientDataSet1AfterPost(DataSet: TDataSet); begin ClientDataSet1.ApplyUpdates(0); end;
Laboratorium nr 1 Zapoznanie się z komponentami dbexpress w środowisku Delphi Umieszczamy na formie zestaw komponentów potrzebnych do zrealizowania połączenia z bazą MySQL. TSQLConnection TDataSetProvider TDataSource TSQLDataSet TClientDataSet Poszczególne zakładki można znaleźć w kategoriach jak niżej: komponent TSQLConnection TSQLDataSet TDataSetProvider TClientDataSet TDataSource kategoria dbexpress dbexpress Data Access Data Access Data Access Konfigurujemy poszczególne komponenty kojarząc je ze sobą: 1. SQLConnection1 Komponent odpowiedzialny za połączenie z serwerem baz danych. ConnectionName MySQLConnection LoginPrompt False Params HostName student1.am.gdynia.pl Database studenttm User_Name studenttm Password studenttm Sprawdź połączenie z bazą danych zmieniając właściwość Connected z False na True. 2. SQLDataSet1 Komponent realizujący zapytania języka SQL (właściwości CommandType i CommandText) SQLConnection SQLConnection1 3. SQLDataSetProvider1 DataSet SQLDataSet1
4. ClientDataSet1 ProviderName 5. DataSource1 DataSet SQLDataSetProvider1 ClientDataSet1 Następnie na formie położyć komponent DBGrid (kategoria Data Controls). Komponent ten jest dynamiczną tabelką umożliwiającą wyświetlanie danych pochodzących z komponentu DataSourde1. Powiązanie odbywa się za pomocą właściwości DataSource DataSource1. Polecenie 1 Wyświetlić zawartość tabeli zbiorniki znajdującej się na zdalnym serwerze student1. Połączenie zostało już skonfigurowane. Aby wyświetlić całą zawartość tabeli należy zmodyfikować właściwości komponentu SQLDataSet1. CommandType CommandText cttable zbiorniki Aby zobaczyć wyniki należy zmienić właściwość Active komponentu ClientDataSet1 z False na True. Polecenie 2 Przygotować aplikację składającą się z pola tekstowego (Memo), przycisku (Button) oraz tabeli (DbGrid). W momencie kliknięcia na przycisk wykonane zostanie zapytanie języka SQL wpisane przez użytkownika do pola Memo. Wynik w DBGrid ie. Ustawiamy właściwość komponentu SQLDataSet1 CommandType ctquery Ponieważ zmiana zapytań w komponencie SQLDataSet1 możliwa jest tylko w momencie, gdy żadne inne elementy nie są dowiązane pierwszą czynnością jest wyłączenie elementów podłączonych. W tym przypadku jest to komponent ClientDataSet właściwość Active. Następnie wpisujemy zapytanie SQL z komponentu Memo do komponentu SQLDataSet. Uaktywnienie komponentu ClientDataSet spowoduje wyświetlenie odpowiedzi w komponencie DBGrid. Kod źródłowy może wyglądać następująco: procedure TForm1.BitBtn1Click(Sender: TObject); begin ClientDataSet1.Close; SQLDataSet1.CommandText := Memo1.Text; ClientDataSet1.Open; end; Wykonanie metody Close równoważne jest wykonaniu podstawienia Active := False. Analogicznie metoda Open odpowiada podstawieniu Active := True. W stworzonej przez siebie aplikacji potrenuj zadawanie pytań. 1) Pokaż całą tabelę zbiorniki.
2) Pokaż nazwy tych zbiorników, które są co najmniej w połowie zapełnione. (kolumna Zapelnienie symbolizuje zapełnienie zbiornika 0 puste, 100 pełne) 3) Pokaż wszystkie zbiorniki balastowe. 4) Pokaż zbiorniki, które zapełnione są w zakresie <25,75>. 5) Pokaż zbiorniki, których przeznaczeniem jest paliwo lekkie i paliwo ciężkie. 6) Pokaż wszystkie dostępne kategorie przeznaczenia zbiorników. 7) Ile jest zbiorników w poszczególnych kategoriach? 8) Jaka jest maksymalna pojemność wśród wszystkich zbiorników? 9) Ile ton paliwa znajduje się na statku? 10) Ile ton paliwa można pobrać w najbliższym porcie pamiętając, że zbiorniki mogą być zapełnione maksymalnie w 94%?
Laboratorium nr 2 Aplikacje i bazy danych Zestaw połączenie z bazą danych tak jak w poprzednim ćwiczeniu. Na formie należy umieścić komponent ComboBox. W momencie startu aplikacji powinien wypełnić się danymi o przeznaczeniu zbiorników. Przykładowy kod może być następujący. 01 procedure TForm1.FormCreate(Sender: TObject); 02 begin 03 ClientDataSet1.Close; 04 SQLDataSet1.Close; 05 SQLDataSet1.CommandText := 'SELECT DISTINCT przeznaczenie FROM zbiorniki'; 06 SQLDataSet1.Open; 07 SQLDataSet1.First; 08 while not SQLDataSet1.Eof do 09 begin 10 ComboBox1.Items.Add(SQLDataSet1.Fields[0].AsString); 11 SQLDataSet1.Next; 12 end; 13 ComboBox1.ItemIndex := 0; 14 SQLDataSet1.Close; 15 end; Opis kodu 03 - zamknięcie komponentu ClientDataSet1, tylko wtedy, gdy element ten niej jest włączony możliwe jest edytowanie ustawień w komponentach powiązanych (tutaj SQLDataSet1) 04 - zamknięcie komponentu SQLDataSet1 w celu zmian właściwości 05 - wpisanie nowego zapytania SQL 06 - wykonanie zapytania, wyniki znajdują się w komponencie SQLDataSet1 07 - ustawienie się na pierwszym wierszu odpowiedzi 08 - funkcja iteracyjna wykonująca się dopóki nie natrafimy na koniec tabeli wynikowej (End of File) 10 - przypisanie wartości z kolumny o indeksie 0 do właściwości Items komponentu ComboBox1 11 - przesunięcie wskaźnika do następnego wiersza 13 - ustawienie pierwszego elementu z listy ComboBox1 jako aktywnego 14 - zamknięcie komponentu SQLDataSet1 Kolejnym elementem jest obsługa zdarzenia ComboBox1Click. W momencie jest wykonania DbGrid powinien wypełnić się wszystkimi danymi na temat wybranej kategorii przeznaczenia. Wysłane pytanie SQL powinno również pojawić się na komponencie Panel1. procedure TForm1.ComboBox1Change(Sender: TObject); begin ClientDataSet1.Close; SQLDataSet1.Close; Panel1.Caption := 'SELECT * FROM zbiorniki WHERE przeznaczenie="'+combobox1.text+'"'; SQLDataSet1.CommandText := Panel1.Caption; ClientDataSet1.Open end;
Zadania 1. Umieść na formie komponent Edit1. Podczas pracy programu użytkownik wpisuje do niego wartość zapełnienia zbiornika. Po kliknięciu na przycisk w komponencie DBGrid pojawiają się dane wszystkich zbiorników o dokładnie takim zapełnieniu. 2. Na formie znajduje się kolejny komponent Edit2. Po kliknięciu na przycisk w komponencie DBGrid pojawią się wszystkie dane tych zbiorników, których zapełnienie jest większe niż wartość z pola Edit1 i mniejsze niż wartość z pola Edit2. 3. Na formie pojawia się RadioGroup1 z wpisanymi wyrażeniami AND i OR. Zmień zadanie nr 2 tak, aby wybrana opcja komponentu RadioGroup1 wskazywała na relacją pomiędzy dwoma warunkami selekcji. 4. Do zad 3 dołóż warunek na przeznaczenia zbiornika (komponent ComboBox1)