R07-04.DOC

(461 KB) Pobierz
Szablon dla tlumaczy

Rozdział 7. Bazodanowa architektura Delphi

W niniejszym rozdziale zajmiemy się obsługą zewnętrznych baz danych przez aplikacje stworzone za pomocą Delphi. Mimo iż do zrozumienia treści rozdziału konieczne jest pewne doświadczenie w pracy z bazami danych, to jednak może on stanowić wprowadzenie do tematyki tworzenia aplikacji bazodanowych wysokiej jakości. Również znawcy tematu znajdą tu ciekawe przykłady. Delphi 6 oferuje kilka mechanizmów dostępu do danych, które przedstawimy tu w zarysie, zaś w następnych rozdziałach zajmiemy się niektórymi z nich bardziej szczegółowo.

Typy baz danych

Wzorując się na systemie pomocy, możemy podzielić obsługiwane przez Delphi 6 technologie bazodanowe na poniższe cztery grupy, z których każda związana jest z określoną stroną w palecie komponentów:

·         BDE — zawiera komponenty wykorzystujące mechanizm Borland Database Engine (BDE). Mechanizm ten oferuje szeroką gamę funkcji API organizujących współpracę z bazami danych. Znakomicie ułatwia obsługę baz danych Paradox i dBase, jest jednak najbardziej skomplikowany pod względem procedury instalacyjnej aplikacji końcowych.

·         ADO — to grupa komponentów wykorzystujących ActiveX Data Objects (ADO), zapewniających dostęp do baz danych za pośrednictwem mechanizmu OLEDB. Obiekty ADO stanowią standard Microsoftu; dostępna jest bogata oferta sterowników zapewniających ich współpracę z rozmaitymi serwerami baz danych.

·         dbExpress — technologia ta, posługując się efektywnymi sterownikami, zapewnia najszybszy dostęp do informacji przechowywanych w bazach danych. Komponenty tej grupy mają charakter uniwersalny, dostępne są także na platformie Linuksa. Uniwersalizm ten przesądza jednak o stosunkowo ubogim repertuarze możliwości w zakresie manipulowania danymi.

·         InterBase — komponenty tej grupy umożliwiają bezpośredni dostęp do serwera InterBase, z pominięciem warstwy pośredniej (engine layer).

Architektura bazy danych

 

Z punktu widzenia aplikacji Delphi, przepływ informacji związanej z zarządzaniem bazami danych podzielić można na ściśle zdefiniowane etapy. Każdemu z nich odpowiada określona grupa komponentów realizujących specyficzne funkcje. Podział ten został schematycznie przedstawiony na rysunku 7.1.

Rysunek 7.1. Architektura bazy danych z punktu widzenia Delphi 6

 

Jak widać, interfejs użytkownika komunikuje się ze zbiorami danych poprzez pośrednią warstwę źródła danych (datasource), reprezentowaną przez komponent TDataSource. Każdy z omawianych na wstępie typów baz danych posługuje się innymi zbiorami danych, zaznaczonych w sposób symboliczny na rysunku 7.1; abstrakcyjnym komponentem reprezentującym zbiór danych jest komponent TDataSet[1].

Połączenia z serwerami baz danych

Ostatnim ogniwem schematu na rysunku 7.1 jest połączenie z danymi, zapewniające fizyczny dostęp do informacji. Każdy z czterech wymienionych typów baz danych posługuje się innym komponentem połączeniowym, wywodzącym się z klasy TCustomConnection:

·         TDataBase jest komponentem połączeniowym dla zbiorów danych opartych na technologii BDE — TTable, TQuery i TStoredProc. Jego wykorzystanie opisane zostało w rozdziale 28. książki „Delphi 4. Vademecum profesjonalisty” („Aplikacje bazodanowe typu klient-serwer”).

·         TADOConnection realizuje połączenie z bazami danych ADO, jak MS Access czy MS SQL. Komponentami zbiorów danych ADO są TADODataSet, TADOTable, TADOQuery, i TADOStoredProc. Technologią ADO zajmiemy się dokładniej w rozdziale 9.

·         TSQLConnection to komponent połączeniowy dla zbiorów danych opartych na technologii dbExpress. Są one efektywnymi, jednokierunkowymi (unidirectional) zbiorami danych reprezentowanymi przez komponenty TSQLDataSet, TSQLTable, TSQLQuery i TSQLStoredProc. Technologii dbExpress poświęcony jest rozdział 8. niniejszej książki.

·         TIBDatabase jest komponentem połączeniowym dla zbiorów danych typu Interbase Express — TIBDataSet, TIBTable, TIBQuery i TIBStoredProc. Zrezygnowaliśmy w niniejszej książce z opisu komponentów Interbase Express, gdyż ich realizacja stanowi w dużej części naśladownictwo innych metod połączeniowych.

 

Elementy wspólne dla wszystkich rodzajów połączeń składają się na definicję klasy TCustomConnection. Zawiera ona metody, właściwości i zdarzenia związane z:

·         nawiązywaniem i rozłączaniem połączenia z repozytoriami danych,

·         logowaniem i nawiązywaniem bezpiecznego połączenia,

·         zarządzaniem danymi.

 

Jest oczywiste, iż mimo owych wspólnych elementów funkcjonalnych, każdy z wymienionych komponentów połączeniowych posiada pewne charakterystyczne cechy, wynikające ze specyfiki docelowego repozytorium danych. Połączenie realizowane dla komponentów ADO różni się więc pod wieloma względami od połączenia realizowanego dla komponentów BDE — o czym możesz się przekonać studiując rozdziały 8. i 9. niniejszej książki oraz rozdział 28. „Delphi 4. Vademecum profesjonalisty”.

 

Zbiory danych

Zbiór danych (dataset) może być postrzegany jako dwuwymiarowa struktura kolumn (columns) i wierszy (rows). Każda kolumna, zwana też polem ( field) grupuje w sobie dane  tego samego rodzaju, natomiast kolejne wiersze, zwane też rekordami (records), stanowią kolejne pozycje danych w zbiorze. Komponentem VCL, ujmującym w sposób abstrakcyjny ideę zbioru danych jest komponent TDataSet, zawierający właściwości i metody niezbędne do nawigowania wśród danych i manipulowania nimi, i stanowiący tym samym klasę bazową dla komponentów realizujących konkretne zbiory danych związane z różnorodnymi technologiami bazodanowymi.

Aby uniknąć niejednoznaczności w dalszej części lektury, musimy zdefiniować kilka niezbędnych pojęć i używać ich tylko w tym znaczeniu. Oto one:

·         Zbiór danych (dataset) jest — zgodnie z tym, co powiedziano przed chwilą — uporządkowaną kolekcją rekordów; organizację każdego rekordu, taką samą dla wszystkich rekordów, określają jego pola, z których każde reprezentuje daną określonego typu (liczbę całkowitą, łańcuch znaków, liczbę w postaci znakowo-dziesiętnej, grafikę itp.).

·         Tabela (table) jest specjalnym typem zbioru danych, najczęściej posiadającym fizyczną postać pliku dyskowego. Komponentami reprezentującymi różnorodne tabele są m.in. TTable, TADOTable, TSQLTable i TIBTable.

·         Zapytanie (query) również stanowi konkretyzację zbioru danych, jednak nie „zmaterializowaną” w tak ścisły sposób jak tabela, lecz stanowiącą swego rodzaju „tabelę tymczasową”, która jest (zazwyczaj) wynikiem żądania skierowanego pod adresem serwera. Zapytanie reprezentowane jest m.in. przez komponenty TQuery, TADOQuery, TSQLQuery i TIBQuery.

 

Notatka

Jak wspominaliśmy na wstępie, niniejszy rozdział nie jest przeznaczony dla nowicjuszy i nie zawiera obszernego wprowadzenia w problematykę programowania obsługi baz danych. Jeżeli określenia: baza danych, tabela czy indeks brzmią dla Ciebie raczej obco, powinieneś uzupełnić swą wiedzę korzystając z podręczników bardziej podstawowych[2].

 

Otwieranie i zamykanie zbioru danych

Jakakolwiek operacja na zbiorze danych musi być poprzedzona jego otwarciem. Zadanie to wykonuje metoda Open() klasy TDataSet:

 

Table1.Open;

Wywołanie to jest równoważne ustawieniu na True właściwości Active:

 

Table1.Active := True;

Czynnością wieńczącą wszystkie operacje na zbiorze danych jest jego zamknięcie, dokonywane przez wywołanie metody Close()

 

Table1.Close;

równoważne ustawieniu właściwości Active na False:

Table1.Active := False;

Wskazówka

Jeżeli wykorzystujesz zbiory danych zlokalizowane na serwerze SQL, otwarcie pierwszego ze zbiorów tego serwera poprzedzone jest nawiązaniem połączenia (connection) z serwerem, zaś zamknięcie ostatniego z tych zbiorów powoduje rozłączenie się z serwerem (disconnection). Ponieważ operacje połączenia i rozłączenia wymagają zawsze nieco czasu, korzystne może okazać się użycie komponentu TDatabase w celu nawiązania permanentnego połączenia z serwerem w sytuacji, kiedy opisane przed chwilą połączenia (rozłączenia) zdarzałyby się nazbyt często. Niebawem powrócimy do tego zagadnienia.

O tym, jak podobne jest otwieranie (zamykanie) różnych typów zbiorów danych, zaświadczyć może kod prezentowany na wydruku 7.1.

 

Wydruk 7.1. Otwieranie i zamykanie przykładowych zbiorów danych

unit MainFrm;

interface

 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, FMTBcd, DBXpress, IBDatabase, ADODB, DBTables, DB, SqlExpr,

  IBCustomDataSet, IBQuery, IBTable, StdCtrls;

 

type

  TForm1 = class(TForm)

    SQLDataSet1: TSQLDataSet;

    SQLTable1: TSQLTable;

    SQLQuery1: TSQLQuery;

 

    ADOTable1: TADOTable;

    ADODataSet1: TADODataSet;

    ADOQuery1: TADOQuery;

 

    IBTable1: TIBTable;

    IBQuery1: TIBQuery;

    IBDataSet1: TIBDataSet;

 

    Table1: TTable;

    Query1: TQuery;

 

    SQLConnection1: TSQLConnection;

    Database1: TDatabase;

    ADOConnection1: TADOConnection;

    IBDatabase1: TIBDatabase;

    Button1: TButton;

    Label1: TLabel;

    Button2: TButton;

    IBTransaction1: TIBTransaction;

    procedure FormCreate(Sender: TObject);

    procedure Button1Click(Sender: TObject);

    procedure FormClose(Sender: TObject; var Action: TCloseAction);

    procedure Button2Click(Sender: TObject);

  private

    { Private declarations }

    procedure OpenDatasets;

    procedure CloseDatasets;

  public

    { Public declarations }

  end;

 

var

  Form1: TForm1;

 

implementation

 

{$R *.dfm}

 

procedure TForm1.FormCreate(Sender: TObject);

begin

  IBDatabase1.Connected    := True;

  ADOConnection1.Connected := True;

  Database1.Connected      := True;

  SQLConnection1.Connected := True;

end;

 

procedure TForm1.Button1Click(Sender: TObject);

begin

  OpenDatasets;

end;

 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

  CloseDatasets;

  IBDatabase1.Connected    := false;

  ADOConnection1.Connected := false;

  Database1.Connected      := false;

  SQLConnection1.Connected := false;

end;

 

procedure TForm1.CloseDatasets;

begin

 

  // rozłączenie ze zbiorami dbExpress

  SQLDataSet1.Close;  // lub Active := false;

  SQLTable1.Close;    // lub Active := false;

  SQLQuery1.Close;    // lub Active := false;

 

  // rozłączenie ze zbiorami ADO

  ADOTable1.Close;    // lub Active := false;

  ADODataSet1.Close;  // lub Active := false;

  ADOQuery1.Close;    // lub Active := false;

 

  // rozłączenie ze zbiorami Interbase Express

  IBTable1.Close;    // lub Active := false;

  IBQuery1.Close;    // lub Active := false;

  IBDataSet1.Close;  // lub Active := false;

 

  // rozłączenie ze zbiorami BDE

  Table1.Close;    // lub Active := false;

  Query1.Close;    // lub Active := false;

 

  Label1.Caption := 'Zbiory danych są zamknięte.'

end;

 

procedure TForm1.OpenDatasets;

begin

 

  // połączenie ze zbiorami dbExpress

  SQLDataSet1.Open;  // lub Active := true;

  SQLTable1.Open;    // lub Active := true;

  SQLQuery1.Open;    // lub Active := true;

 

  // połączenie ze zbiorami ADO

  ADOTable1.Open;    // lub Active := true;

  ADODataSet1.Open;  // lub Active := true;

  ADOQuery1.Open;    // lub Active := true;

 

  // połączenie ze zbiorami Interbase Express

  IBTable1.Open;    // lub Active := true;

  IBQuery1.Open;    // lub Active := true;

  IBDataSet1.Open;  // lub Active := true;

 

  // połączenie ze zbiorami BDE

  Table1.Open;    // lub Active := true;

  Query1.Open;    // lub Active := true;

 

  Label1.Caption := 'Zbiory danych są otwarte.';

end;

 

procedure TForm1.Button2Click(Sender: TObject);

begin

  CloseDatasets;

end;

 

end.

 

Powyższy moduł jest częścią projektu ...

Zgłoś jeśli naruszono regulamin