Delphi - Database application tutorial (slot)
1. Inleiding
In de voorgaande papers van deze database-basics turorial hebben we
vooral naar de theorie gekeken.
In dit slot paper gaan we een eenvoudige database applicatie schrijven.
De applicatie toont de hiervoor besproken technieken. Het is geen compleet
afgewerkte applicatie, daar het
alleen de bedoeling is om de technieken te tonen.
Download hier de source
2. De database tabellen
Het doel van de applicatie is om projecten te beheren. Bij deze projecten kunnen
de tekeningen toegevoegd worden.
De gehele applicatie bestaat uit drie tabellen te weten :
Het betreft hier Paradox tabellen, met de volgende structuur :
* = Index van de tabel, A = Alpha numeriek (karakter) D=Datumveld.
Project.db
|
Drawing.db
|
DrawProject.db
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
De tabellen Project en drawing zijn middels een meer-op-meer relatie aan elkaar
verbonden.
Het komt er opneer dat een tekening tot meerdere projecten kan toehoren, en dat een
project meer tekeningen kan hebben.
De relatie wordt in de tabel DrawProject vastgelegd.
3. De Applicatie
De applicatie voorziet in één mainform waarop een tab-control is geplaatst met
drie tabsheets.
Het eerste tabsheet toont de projecten. Hier kunnen :
Het tweede tabsheet toont een browse overzicht van alle tekeningen, hier kunnen
tekeningen toegevoegd, verwijdert en gewijzigd worden.
Het derde tabsheet biedt de mogelijkheid om SQL commando's in te voeren en te
executen.
Zoals gezegd geen complete applicatie, maar wel één met alle database technieken
in zich.
De volgende Forms behoren tot het project :
frmMain - het hoofdform
dmProject - een datamodule die de databasecomponenten bevat.
frmAddItem - een 'algemeen' form die met behulp van een klasse tekeningen toe voegt
aan een project. (Hierover later meer)
modBrowse - een unit, geen form, die een klasse definitie voor het toevoegen van de
tekeningen verzorgt.
3.1 Het instellen van de database componenten
Als eerste dient er middels de BDE-Administrator een database alias gemaakt te worden, met de volgende instellingen :

De alias heet Project en verwijst naar een fysieke lokatie op schijf. (Vul
bij path de directory in)
Nu dit gedaan is kunnen we de database componenten in de datamodule dmProject
plaatsen en instellen.
Wat hebben we nodig :

Hierboven staat een screendump van de datamodule dmProject. De instellingen per component :
Het instellen van de properties van de data-access componenten :
| tbProject | Query | ||
| DataBasename | Project | DataBaseName | Project |
| Name | tbProject | Name | Query |
| TableName | Project.db | ||
| tbProject is voor het managen van de projectgegevens. | Query is het component waarmee alle TTables geraadpleegt kunnen worden middels SQL | ||
| dsProject | dsQuery | ||
| DataSet | tbProject | Dataset | Query |
| Name | dsProject | Name | dsQuery |
| dsProject is de datasource behorende bij tbProject. | dsQuery is de datasource behorende bij Query. | ||
| tbDrawing | dsDrawingToProject | ||
| DataBaseName | Project | Dataset | tbDrawingToProject |
| Name | tbDrawing | Name | dsDrawingToProject |
| TableName | Drawing.db | ||
| tbDrawing is voor het managen van de tekeninggegevens. | dsDrawingToProject is de datasource behorende bij tbDrawingToProject. | ||
| tbPrjDwg | tbDrawingToProject | ||
| DataBaseName | Project | DataBaseName | Project |
| Name | tbPrjDwg | Name | tbDrawingToProject |
| TableName | DrawProject.db | TableName | Drawing.db |
| MasterSource | dsProject | MasterSource | dsPrjDwg |
| MasterFields | Projectnr. | MasterFields | Drawingnr |
| IndexName | OnProjectnr | ||
| tbPrjDwg toont de tekeningen die bij het huidige project horen. Ofwel de mastersource is dsProject, zodat tbPrjDwg een resultset toont van alleen die tekening uit tabel drawproject.db die als projectnr. het huidige projectnr, uit tbProject hebben. Merk op dat de IndexName wijst naar de secondary index OnProjectnr. | tbDrawingToProject toont de tekeninggegevens van de huidige tekening in tbPrjDwg. De mastersource is dsPrjDwg. Deze TTable toont altijd maar één record, namelijk op basis van het huidige tekeningnr in tbPrjDwg. | ||
| dsPrjDwg | |||
| DataSet | tbPrjDwg | ||
| Name | dsPrjDwg | ||
| dsPrjDwg is de datasource behorende bij tbPrjDwg. | |||
De dataware componenten van het programma moeten als volgt ingesteld worden :

Onder de tab Drawings bevindt zich een DBGrid waar de tekeningen in beheerd worden, deze heeft als datasource dsDrawing.
3.2 Het toevoegen van tekeningen aan een project
Middels de knop Add a drawing to this project kunnen tekeningen
toegevoegd worden aan het huidige project.
Er wordt een tekening gekozen uit de tabel Drawing, deze wordt in combinatie met
het project nummer toegevoegd in de tabel tbPrjDwg.
Om de tekening te kiezen moet een apart form gemaakt worden waarin alle tekeningen
getoond worden.
Dit form zouden we natuurlijk kunnen bouwen op de manier zoals hierboven door
handig om te gaan met de datasources en componenten.
Voor dit demoprogramma zou dit goed werken. Echter in een echte applicatie zou je
misschien ook projecten willen toevoegen aan tekeningen, of
willen tooevoegen aan 'wat dan ook'.
Het is dus zaak het 'toevoeg' form zo abstract mogelijk te houden, zodat het voor
allerlei toevoeg acties hergebruikt kan worden.
Hoe zou dit gerealiseerd kunnen worden :
De punten 1 en 2 kunnen op zich best voldoen, maar brengen veel (dezelfde) code
in ons programma waar we ons eigenlijk niet mee bezig willen houden.
Verder hebben zij als nadeel dat als er onverhoopt een wijziging plaatsvindt die
onherroepelijk op meerdere plaatsen in de code zal moeten worden doorgevoerd.
Uit OOP oogpunt is optie 3 de beste oplossing, deze hebben we in deze applicatie
dan ook toegepast.
Het toevoegscherm :
![]() |
Het toevoegscherm is heel eenvoudig, en bestaat uit
een DBGrid en twee buttons. Er worden tijdens het ontwerp geen database properties geset. We willen immers dit scherm voor meerdere tabellen gebruiken. |
De volgende class verzorgt de instellingen van het toevoegscherm : (modBrowse.pas)
/////////////////////////////////////////////////////////////////////////////
// modBrowse class
// Used for setting the frmAddItem form
//
// (c) beensoft@yahoo.com http://surf.to/beensoft
////////////////////////////////////////////////////////////////////////////
unit modBrowse;
interface
uses DB, Classes;
resourcestring
SAddDWG = 'Add a drawing';
type
TDBBrowseClass = class
private
{ Private declarations }
FDataSource : TDataSource;
FFieldCaptionList : TStrings;
FFieldList : TStrings;
public
{ Public declarations }
Constructor CreateBrowse (aDataSource : TDataSource);
Destructor Destroy; Override;
function GetCaption : string; virtual; abstract;
function GetFieldCaptionList : TStrings; virtual;
function GetFieldList : TStrings; virtual;
property Datasource : TDataSource read FDataSource write FDatasource;
property FieldCaptionList : TStrings read FFieldCaptionList write FFieldCaptionList;
property FieldList : TStrings read FFieldList write FFieldList;
end;
//TDBDWGBrowse : Adding drawings
type
TDBDWGBrowse = class(TDBBrowseClass)
private
{ Private declarations }
public
{ Public declarations }
function GetCaption : string; override;
function GetFieldCaptionList : TStrings; override;
function GetFieldList : TStrings; override;
end;
// Here you could create the TDBPrjBrowse for adding projects
implementation
{ TDBBrowse }
constructor TDBBrowseClass.CreateBrowse(aDataSource: TDataSource);
begin
Inherited Create;
FDataSource := aDataSource; // the datasource
FFieldCaptionList := TStringList.Create; // the collumncaptions of the grid
FFieldList := TStringList.Create; // the fields in the grid
end;
Destructor TDBBrowseClass.Destroy;
begin
FFieldCaptionList.Free; // free the caption stringlist
FFieldList.Free; // free the field list
Inherited Destroy;
end;
function TDBBrowseClass.GetFieldCaptionList : TStrings;
begin
FFieldCaptionList.Clear; // clear the list (should be clear)
Result := FFieldCaptionList;
end;
function TDBBrowseClass.GetFieldList : TStrings;
begin
FFieldList.Clear; // clear the list (should be clear)
Result := FFieldList;
end;
{ TDBDWGBrowse }
function TDBDWGBrowse.GetCaption: string;
begin
Result := SAddDWG; //set the caption for DWG adding
end;
// For the captions of the grid columns
function TDBDWGBrowse.GetFieldCaptionList : TStrings;
begin
FFieldCaptionList.Add('Drawingnr');
FFieldCaptionList.Add('Description');
result := FFieldCaptionList;
end;
// The FieldName list
function TDBDWGBrowse.GeTFieldList : TStrings;
begin
FFieldList.Add('DRAWINGNR');
FFieldList.Add('DESCRIPTION');
result := FFieldList;
end;
end.
|
De main class wordt alleen gebruikt om de class te initialiseren (datasource) en
om de stringlists te creëen en op te ruimen.
De virtual gedeclareerde methods kunnen in the subclass override worden met de specifieke
wensen, zoals te gebruiken velden in de grid en captions.
Zoals deze class gebruikt wordt is nog steeds vrij statisch, je zou immers ook de
te gebruiken velden via de aanroep kunnen initialiseren.
Indien dit wenselijk is zou je er bijna een component van kunnen maken waarin via
properties alles ingesteld kan worden.
Dit is een goed idee voor het volgende te bouwen component !, het TDBBrowse
component.
De aanroep vanuit ons programma gaat als volgt : (frmMain)
procedure TfrmMain.SetGridProps; // method can be used generally
var I : Integer; // Browse : TDBBrowse
begin
frmAddItem.DBGridItems.Columns.Clear; // Clear the 'normal'fieldlist
For I := 0 to Browse.GetFieldList.Count - 1 do // Add field and caption to DBGrid
with frmAddItem do
begin
DBGridItems.Columns.Add;
DBGridItems.Columns[I].FieldName := Browse.GetFieldList.Strings[I];
DBGridItems.Columns[I].Title.Caption := Browse.GetFieldCaptionList.Strings[I];
end;
end;
procedure TfrmMain.btnAddDWGClick(Sender: TObject); // Add a drawing button click
begin
// First create the DWGBrowse object
Browse := TDBDWGBrowse.CreateBrowse(dmProject.dsDrawing);
Try
frmAddItem := TFrmAddItem.Create(self); // Create the form
With frmAddItem do
begin
Caption := DWGBrowse.GetCaption; // Set the caption of the form
DBGridItems.DataSource := Browse.DataSource; // Parse the datasource to grid
SetGridProps; // Set grid properties method
ShowModal; // show the form
With dmProject do // Insert the drawing/project in tabel tbPrjDwg
begin
tbPrjDwg.Insert;
tbPrjDwg.FieldByName('DRAWINGNR').AsString := tbDrawing.FieldByName('DRAWINGNR').AsString;
tbPrjDwg.FieldByName('PROJECTNR').AsString := tbProject.FieldByName('PROJECTNR').AsString;
tbPrjDwg.Post;
end;
end;
Finally
frmAddItem.Free; // free the form
Browse.Free; // free the object
end;
end;
|
3.3 Het maken van een query
Op het derde tabsheet van de tabcontrol kunnen we in een memo component SQL
commando's invoeren. Die middels de button Execute query
uitgevoerd kan worden. De buttonclick event ziet er alsvolgt uit :
procedure TfrmMain.btnExecuteSQLClick(Sender: TObject);
begin
with dmProject do
begin
Query.Close;
Query.SQL.Clear;
Query.SQL := mmSQL.Lines; // assign memolines to SQL
Query.Open;
end;
end;
|
Het resultaat van de querie, de resultset, wordt getoond in de DBGrid.
Middels deze demo-applicatie hebben wij getracht enkele delphi-database
technieken duidelijk te maken.
Hiermee is de Tutorial Delphi basic-databasetechnieken compleet.