Delphi 6 Relationnel

Cette page a pour but de vous aider à construire une application de base de données relationnelle avec dbExpress.

Suivez les commandes et captures d'écrans.

Article lu   fois.

L'auteur

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Introduction

Dans dbExpress avec Delphi 6 nous avons construit un accès simple à une table unique. Nous allons maintenant aborder 2 types de relations :

  • La relation d'une table maître avec une table détail.
  • La relation LookUp.

II. Ce qu'il vous faut

  • Delphi 6 Pro ou Entreprise
  • Delphi 6 et InterBase 6 sur CD avec la Documentation sont aussi disponible auprès du Centre Officiel de Borland : Diffus'Log - Tél : 01 34 63 07 01.
  • Il vous faut aussi l'application et le fichier MaDatabase.gdb résultant de Delphi 6 et InterBase 6, ainsi que l'application développée dans dbExpress avec Delphi 6.

III. Création des tables complémentaires

Pour la création des tables, nous utilisons les IBX qui gèrent directement InterBase.
Pour cela complétons l'application Delphi 6 et InterBase 6 dans le but de générer les tables :
À partir de la palette, placez sur le DataModule 2 IBTable,

Image non disponible

et modifiez les propriétés pour la table Appels

Objet Propriété Valeur
IBTable1 Name IBTableAppels
IBTableAppels Database IBDatabase1
IBTableAppels TableName APPELS Ignorez messages la base est fermée
IBTableAppels FieldDefs cliquez sur … et tapez 5 fois sur la touche Ins
Modifier les noms des champs ainsi que leurs propriétés :    
IBTableAppelsField1 Name PK_APPELS
PK_APPELS DataType ftInteger
PK_APPELS Attributes [faRequired]
DATEAPPEL DataType ftDateTime
TYPEDAPPEL DataType ftString
TYPEDAPPEL Size 12
RAPPELER DataType ftBoolean (sera traduit en SmallInt)
COUT DataType ftCurrency (sera traduit en Double Precision)
IBTableAppels FieldDefs cliquez sur … et tapez 1 fois sur la touche Ins
Modifier le nom du champ ainsi que sa propriété :    
IBTableAppelsFieldIndex1 Name PK_APPELS
PK_APPELS Options [ixPrimary]

et les propriétés pour la table TypesDAppel

Objet Propriété Valeur
IBTable1 Name IBTableTypesDAppel
IBTableTypesDAppel Database IBDatabase1
IBTableTypesDAppel TableName TYPESDAPPEL
IBTableTypesDAppel FieldDefs cliquez sur … et tapez 2 fois sur la touche Ins
Modifier les noms des champs ainsi que leurs propriétés :    
IBTableTypesDAppelField1 Name PK_TYPESDAPPEL
PK_TYPESDAPPEL DataType ftInteger
PK_TYPESDAPPEL Attributes [faRequired]
TYPEDAPPEL DataType ftString
TYPEDAPPEL Size 12
IBTableTyoesDAppel FieldDefs cliquez sur … et tapez 1 fois sur la touche Ins
Modifier le nom du champ ainsi que sa propriété :    
IBTableAppelsFieldIndex1 Name PK_TYPESDAPPEL
PK_TYPESDAPPEL Options [ixPrimary]

On n'introduit pas d'autres composants, pusique notre seul but est de créer les tables.

Pour que les tables soient crées, on ajoute :

 
Sélectionnez
IBTableAppels.CreateTable;
IBTableTypesDAppel.CreateTable;

en fin de la méthode IBDatabase1Open.

Et on exécute une fois le programme.

Note : La création de tables à travers l'IDE comme ci-dessus ou par CREATE TABLE est une affaire de goût.
Ceux qui préfèrent CREATE TABLE, peuvent s'inspirer de Ma première base InterBase et lancer l'ordre suivant (qui n'est volontairement pas formatté pour permettre un copier/coller dans l'Interactive SQL d'IBConsole) :

 
Sélectionnez
CREATE TABLE "APPELS" ( "PK_APPELS" INTEGER NOT NULL, "DATEAPPEL" TIMESTAMP,
  "TYPEDAPPEL" VARCHAR(12), "RAPPELER" SMALLINT, "COUT" DOUBLE PRECISION,
  "PK_NOMS" INTEGER NOT NULL, CONSTRAINT "PK_APPELS" PRIMARY KEY ("PK_APPELS") );
CREATE TABLE "TYPESDAPPEL" ( "PK_TYPESDAPPEL" INTEGER NOT NULL,
"TYPEDAPPEL" VARCHAR(12), CONSTRAINT "PK_TYPESDAPPEL" PRIMARY KEY ("PK_TYPESDAPPEL") );

Les tables étant créées, nous allons maintenant voir comment Delphi prend en compte la logique relationnelle.

IV. Relation mère/fille

Pour relier la table Appels à la forme, nous créons une chaîne dbExpress identique à celle que nous avons établie dans dbExpress avec Delphi 6 pour la table Noms. Il suffit d'ailleurs d'aller sur le data module, de sélectionner l'ensemble des composants sauf SQLConnection1, et de faire un copier coller. (Les composants viennent se coller exactement sur les composants copiés : descendez les tous en faisant [Ctrl + Maj + Bas] avant de les désélectionner).

Il suffit maintenant d'adapter les propriétés :

Composant Propriété Valeur
SQLDataSet1 Name SQLDataSetAppels
SQLDataSetAppels SQLConnection SQLConnection1
SQLDataSetAppels CommandText select * from APPELS
DataSetProvider1 Name DataSetProviderAppels
DataSetProviderAppels DataSet SQLDataSetAppels
ClientDataSet1 Name ClientDataSetAppels
ClientDataSetAppels ProviderName DataSetProviderAppels
DataSource1 Name DataSourceAppels
DataSourceAppels DataSet ClientDataSetAppels
Image non disponible
Image non disponible

Comment allons-nous indiquer la liaison mère/fille ?

Tout simplement en indiquant que ClientDataSetAppels dépend de ClientDataSetNoms à l'aide des propriétés suivantes :

Composant Propriété Valeur
ClientDataSetAppels MasterSource DataSourceNoms
ClientDataSetAppels MasterFields PK_NOMS (1)
ClientDataSetAppels IndexFieldNames PK_NOMS;DATEAPPEL

(1) Ne cliquez pas sur les … de la ligne MasterField : en le faisant vous provoquez les choses suivantes :

  • Activation de la connexion SQLConnection1
  • Chargement de FieldDefs
  • Ouverture d'une dual liste pour établir la liaison.

Évidemment, il est plus agréable d'avoir à choisir dans une liste. Mais vous pouvez souhaiter contrôler le moment de l'ouverture de la connexion à l'exécution en démarrant avec Connected à False. De plus, vous pouvez souhaiter que les champs FieldDefs du ClientDataSet soient reconstitués automatiquement à l'exécution pour refléter d'éventuelle modification de la structure de la table. Si néanmoins vous avez affiché la dual liste, il vous suffit de

  • Mettre dans l'IDE SQLConnection1.Connected à False
  • et, toujours dans l'IDE, ClientDataSetAppels.StordeDefs à False

Pour terminer, nous ajoutons la procédure d'ouverture de la table Appels :

 
Sélectionnez
procedure TDataModule1.ClientDataSetAppelsOpen;
begin
  ClientDataSetAppels.Open;
end;

Sur la Forme UnitForm, nous plaçons une grille supplémentaire que nous connections à DataModule1.DataSourceAppels

Objet Propriété Valeur
DBGrid1 Name DBGridAppels

et dans FormShow nous ajoutons l'ordre d'ouverture de la table Appels, ainsi que les mises à jour d'Appels :

 
Sélectionnez
procedure TFormNoms.FormShow(Sender: TObject);
begin
    DBGridNoms.DataSource := DataModule1.DataSourceNoms;
    DataModule1.ClientDataSetNomsOpen;
    DBGridAppels.DataSource := DataModule1.DataSourceAppels;     DataModule1.ClientDataSetAppelsOpen;
end;

procedure TFormNoms.ButtonApplyUpdatesClick(Sender: TObject);
begin
    DataModule1.ClientDataSetNoms.ApplyUpdates(-1);
    DataModule1.ClientDataSetAppels.ApplyUpdates(-1);
end;

procedure TFormNoms.ButtonCancelUpdatesClick(Sender: TObject);
begin
    DataModule1.ClientDataSetNoms.CancelUpdates;
    DataModule1.ClientDataSetAppels.CancelUpdates;
end;

Nous exécutons, et saisissons : les valeurs de liaisons des appels sont préremplies automatiquement, et la relation est totalement gérée.

Image non disponible

Cliquez sur Sauvegarder les modifications avant de sortir de l'application.

Votre premier programme relationnel est prêt.

V. Relation lookup

Nous allons maintenant ajouter un contrôle sur la zone TypeDAppel. En effet, nous souhaitons que ce type appartienne à la table TypesDAppel que nous avons créée au début.

Nous ajoutons la connectique dbExpress de cette table. C'est maintenant une opération qui devient une habitude : il suffit de répéter ce que nous avons fait pour la table Appels pour obtenir ceci :

Image non disponible

Vérifiez sur les composants de la rangée du bas, que vous avez bien mis TypesDAppel partout où il y avait Appels,
et que vous avez

 
Sélectionnez
select * from TYPESDAPPEL

Créez la procédure d'ouverture :

 
Sélectionnez
procedure TDataModule1.ClientDataSetTypesDAppelOpen;
begin
  ClientDataSetTypesDAppel.Open;
end;

Ajoutez une grille sur la forme pour saisir les types d'appels, et complétez les procédures:

 
Sélectionnez
procedure TFormNoms.FormShow(Sender: TObject);
begin
    DBGridNoms.DataSource := DataModule1.DataSourceNoms;
    DataModule1.ClientDataSetNomsOpen;
    DBGridTypesDAppel.DataSource := DataModule1.DataSourceTypesDAppel;     DataModule1.ClientDataSetTypesDAppelOpen;
    DBGridAppels.DataSource := DataModule1.DataSourceAppels;     DataModule1.ClientDataSetAppelsOpen;
end;

procedure TFormNoms.ButtonApplyUpdatesClick(Sender: TObject);
begin
    DataModule1.ClientDataSetNoms.ApplyUpdates(-1);
    DataModule1.ClientDataSetTypesDAppel.ApplyUpdates(-1);
    DataModule1.ClientDataSetAppels.ApplyUpdates(-1);
end;

procedure TFormNoms.ButtonCancelUpdatesClick(Sender: TObject);
begin
    DataModule1.ClientDataSetNoms.CancelUpdates;
    DataModule1.ClientDataSetTypesDAppel.CancelUpdates;
    DataModule1.ClientDataSetAppels.CancelUpdates;
end;
Image non disponible

Il nous ne reste qu'a relier cette table avec le champ TypeDAppel de la table appel
Nous allons utiliser la propriété PickList associée à la colonne TypeDAppel de la table Appels :
Dans la forme nous ajoutons la procédure privée suivante :

 
Sélectionnez
procedure TFormNoms.SetTypesDAppelPickList;
var s: string;
begin
  s := '';
  with DataModule1.ClientDataSetTypesDAppel do
  begin
    First;
    while not Eof do
    begin
      s := s + FieldByName('TYPEDAPPEL').AsString + #13;
      Next;
    end;
  end;
  DBGridAppels.Columns[2].PickList.Text := Copy(s, 1, Length(s) - 1);
end;

Cette procédure de rafraîchissement de la liste est activée à la fin de FormShow et de ApplyUpdates en ajoutant la ligne

 
Sélectionnez
SetTypesDAppelPickList;

à la fin des procédures FormShow et ButtonAppluUpdatesClick.

Votre relation LookUp est prête pour la saisie.

VI. Pour aller plus loin

Interbase
Ma première base InterBase
Delphi 6 et InterBase 6
dbExpress avec Delphi 6
Delphi 6 Relationnel
Le bon PLAN d'InterBase
MDA (Model Driven Architecture)
MDA
Programmez avec les diagrammes de Delphi 7
Les objets métiers avec ModelMaker de Delphi 7
Les Design Patterns avec ModelMaker de Delphi 7
Autres articles
Les transactions
Mise à jour de Delphi 6

  

Copyright © 2001 Henry Cesbron Lavau. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.