menu
  Home  ==>  articles  ==>  bdd  ==>  interbase  ==>  interbase_ibx_net   

Interbase Ibx.Net - John COLIBRI.


1 - Introduction

Cet article va vous indiquer comment utiliser le Serveur Interbase fourni avec Delphi en utilisant le version 8 de Delphi. Ce tutorial a plusieurs objectifs:
  • vous présenter comment réaliser des applications utilisant des bases de données Sql en Delphi 8. Tous les exemples ont été codés et les sources sont téléchargeables.
  • effectuer toutes les opérations en Delphi, au lieu d'utiliser des outils annexes tels que WISQL ou IbConfig
  • présenter surtout la partie accès aux données, sans entrer dans le menu détail de la partie visuelle (dbGrid, dbEdit)
Nous nous adressons pour cet article à un programmeur Delphi ayant une idée élémentaire de Delphi: Palette, Inspecteur, OnClick. Tout le reste sera expliqué.

Nous supposons:

  • que Delphi 8 est installé (la version "développeur": pas la version "étudiant" qui n'a pas les bases de données, et pas besoin de la version "Entreprise" ou "Architecte", mais tout marche aussi avec ces deux dernières)
  • qu'Interbase est installé (voyez le tutorial interbase qui détaille cette installation). J'ai utilisé la version Interbase que j'ai installé et que j'utilise couremment avec Delphi 6, mais tout fonctionne bien sûr avec les versions 7 et FireBird.



3 - Les différentes possibilités

Cet article fait part d'une série décrivant les différentes possibilités de gérer des données Interbase en Delphi 6 et Delphi 8. Il convient donc tout d'abord de resituer les différentes possibilités de traitement proposées en Delphi:
  • la gestion de tables Interbase se fait en utilisant un Serveur et un Client fournis par Interbase (et livré avec Delphi). Ceux-ci peuvent être situés sur des PC différents ou sur le même PC. Pour la simplicité des figures, nous supposerons qu'ils sont sur des PC distincts.

  • le Client Interbase ne sait pas gérer tout seul les données. Il faut écrire des applications qui lui envoient des requêtes. Nous pouvons écrire ces applications avec n'importe quel langage qui sait communiquer avec le Client Interbase. Pour notre part nous utiliserons Delphi:

  • Delphi offre plusieurs modules pour communiquer avec le Client Interbase:
    • en Delphi 4 à Delphi 6, le mode le plus ancien et le plus efficace est Interbase Express (alias IBX).

    • en Delphi 6 nous pouvious aussi utiliser dbExpress (alias Midas, alias DataSnap, alias client léger ou programmation multi-niveau):

    • en Delphi 8, Borland a prévu deux modes de programmation:
      • le mode VCL.NET qui fournit une programmation pratiquement identique à la programmation sous Delphi 6, mais par dessus la librairie .NET (au lieu d'être par dessus la librairie Win32).

        Sous VCL.NET

        • Borland a porté la librairie IBX sous Delphi 8, et c'est l'objet de notre article

        • Ainsi que la mécanique générique (indépendante d'Interbase), dbExpress.Net

      • Delphi 8 permet aussi d'utiliser les contrôles .NET (les boutons, les listbox etc). Dans ce cas, nous devons utiliser les couches d'accès aux données fournies par Microsoft. Deux modes:
        • Ado.Net qui est un mode similaire à dbExpress, à la Microsoft

        • le Borland Data Provider qui est une mise en forme de Ado.Net plus efficace et bien plus conviviale. Elle aussi ressemble fort à dbExpress, mais en "plus Delphi" que la librairie précédente



Par rapport à ces architectures, voici les articles que vous pouvez consulter ici:
  • le tutorial interbase: comment utiliser des bases de données en mode Client Serveur (Delphi 6, Ibx). L'article d'initiation le plus complet
  • Interbase dbExpresss: le mode dbExpress (Delphi 6, dbExpress). Le mode qui permet le mieux de comprendre l'architecture Ado.Net qui en est directement issue
  • Interbase Ibx.Net: le portage sous .Net de la mécanique Ibx (Delphi 8, Ibx.Net). Le moyen le plus simple d'utiliser Interbase et Delphi 8. C'est cet article ci.
  • Interbase dbExpress.Net: le portage sous .Net de la mécanique dbExpress (Delphi 8, dbExpress.Net). L'utilisation des techniques VCL pour Interbase ET pour les autres serveurs (Oracle, Sql Server, MyBase etc)
  • Delphi 8 Ado.Net: sous Windows Forms, en l'absence de couche spécifique à Interbase nous pouvons utiliser une mécanique similaire à Odbc et proche d'Ado sous Win32. Cet article présente ce fonctionnement
  • Interbase Borland Data Provider: la voie royale sous Windows Forms, et pour toutes les base, même pour tous les langages


Je crois qu'il vaut mieux lire les articles dans cet ordre, mais vous êtes libre de consulter ce qui vous convient le mieux, quitte à revenir à un autre article au besoin.

Mentionnons au'Interbase peut aussi être utilisé comme moyen de sauvegarde sous ECO, et comme source de données de pages Asp.Net et de Services Web.

Si après ces saines lectures vous souhaitez approfondir vos connaissances, nous serons heureux de vous acueillir lors de nos formations ou de fournir telles prestations de programmation de portage ou d'assistance que vous jugerez utile.


4 - Créer la Base

4.1 - Installation

Comme indiqué au début de cet article, je ne présente pas à nouveau l'installation d'Interbase, pas plus que celle de Delphi 8.

4.2 - Création de la base

Nous allons créer une base contenant les stages offerts par l'Institut Pascal. Nous placerons cette base dans le répertoire "..\data\" (situé au même niveau que le .EXE. Le .ZIP téléchargeable créera ce répertoire automatiquement). Le nom du fichier sera "Institut_Pascal.GDB".

Pour créer la base:
   créez une nouvelle application et appelez-la "p_net_ibx_create_base_3"
   sélectionnez dans la page "Interbase" de la Palette le composant tIbTransaction:

et posez ce composant sur la tForm

   sélectionnez de même une tIbDatabase (situé juste au dessus du précédent dans notre figure et placez-la sur la tForm
   initialisez IbDatabase1.DefaultTransaction vers IbTransaction1
   utilisez un tButton pour créer la base:
  • placez un tButton, nommez-le create_base_, et créez sa méthode OnClick
  • voici le code de cette méthode:

        procedure TForm2.create_database_Click(SenderTObject);
          begin
            IbDatabase1.Close;

            with IbDatabase1 do
            begin
              If FileExists(k_database_pathk_database_name)
                Then begin
                    display('Erase');
                    Exit;
                  end;

              DatabaseName:= k_database_pathk_database_name;
              SqlDialect:= 3;

              with Params do
              begin
                Clear;
                Add('USER "sysdba"');
                Add('PASSWORD "masterkey"');
                Add('PAGE_SIZE 4096');
              end;  

              display('create');

              CreateDatabase;
            end// with IbDatabase1
          end// create_database_Click


   compilez et exécutez
   cliquez Button1
   Delphi 8 crée la base


En fait ce n'est pas tout à fait exact. Avec ma version actuelle de Delphi, la création est refusée:






Une recherche Google indique que cette erreur est connue:






Et comme nous l'avons déjà écrit, ce type d'erreur est semble-t-il assez courant et redouté. Dans le fichier "Delphi 8 2nd Update", Borland cite de nombreuses corrections ayant eu pour objet de faire disparaître ce type de messages. Pour le moment je ne comprends pas ce qui les provoque.

Une recherche Google "Object Reference not Set" fournit 12.400 réponses, les victimes allant de Crystal Report à Excel.

Si vous avez une version plus récente que nous de Delphi 8, il est certain que cette erreur aura été corrigée.



En attendant, pour poursuivre l'exposé, nous vous suggérons:

  • de copier dans le répertoire .._DATA une base de votre choix. Nous avons copié la base INSTITUT_PASCAL.GDB provenant de Tutorial Interbase. Vous pouvez d'ailleurs utiliser le .ZIP de ce Tutorial pour créer sous Delphi 6 une base vierge à l'emplacement de votre choix. Vous pouvez aussi rechercher sur disque EMPLOYEE.GDB qui est la base de démonstration Interbase, et la copier dans ce répertoire.
  • de renommer la base INSTITUT_PASCAL_3.GDB (le changement de nom via un Explorateur Windows est permis)
Vous pouvez télécharger ce projet "net_ibx_create_database_3.zip".

Maintenant que nous disposons d'une base, nous allons utiliser les composants Ibx.Net pour accéder aux données de notre base.

4.3 - Connection à une base

Pour nous connecter à une base Interbase nous allons utiliser une seconde IbDatabase:

Ce composant doit être initialisé avec:

  • dans DataBaseName, la chaîne de connection qui est
    • si nous travaillons en local, le chemin:
              c:\programs\interbase\data\Institut_Pascal_3.gdb
      ou
              ..\data\Institut_Pascal_3.gdb
    • l'URL du PC qui héberge le Serveur:
              127.0.0.1\ c:\programs\interbase\data\Institut_Pascal_3.gdb
              HostName\ c:\programs\interbase\data\Institut_Pascal_3.gdb
              www.jcolibri.com\ c:\programs\interbase\data\Institut_Pascal_3.gdb
  • dans Params, les paramètres propres à Interbase. Dans notre cas, les paramètres par défaut du Serveur, plus le nom d'utilisateur et le mot de passe.
Une fois les propriétés initialisées, nous pouvons tester la connection en basculant tIbDatabase.Connected sur True.

A titre de vérification:
   posez un second tIbDataBase sur la forme
   initialisez IbDatabase2.DatabaseName avec
        ..\data\Institut_Pascal_3.gdb
   cliquez deux fois sur IbDatabase2 pour ouvrir l'éditeur de tIbDatabase
   Delphi présente le dialogue suivant:

   sélectionnez "User Name" et tapez SYSDBA
   sélectionnez "Password" et tapez masterkey
   supprimez la coche de "Login Prompt"
   cliquez le bouton "Test"
   le résultat est:

   fermez l'éditeur en cliquant "Ok"


Notez que:

  • la connection est le test IMPERATIF pour vérifier que nous pouvons travailler en Interbase. Nous recommandons d'effectuer cette connection systématiquement avant de poser des tonnes de composants sur la tForm ou d'écrire des milliers de lignes
  • si nous connectons la base en mode conception, Delphi ouvrira aussi la base lorsque l'exécution sera lancée. Ces deux connections sont comptabilisés par le gestionnaire de licences Interbase comme 2 connections séparées (ce sont bien deux processus Windows). Si vous travaillez en utilisant la version Delphi d'Interbase, il vaut mieux fermer la connection en mode conception, puis la rouvrir lors de l'exécution par:
            tIbDatabase.Open;



5 - Créer une Table

Nous allons créer une table contenant pour chaque formation:
  • un code (par exemple 8)
  • un nom (par exemple "Delphi Interbase")
  • un prix (par exemple 1.400)
Pour cela nous devons envoyer une requête en langage SQL vers le Serveur Interbase.

La syntaxe de cette requête est:

 CREATE TABLE formations_3
     (f_numero INTEGER, f_nom CHARACTER(25), f_jours INTEGER, f_prix NUMERIC(5, 2) )

Il suffit donc de choisir un nom de table, et le nom de chaque colonne avec son type.

Parmi les types autorisés par Interbase citons:

  • INTEGER pour les valeurs entières 32 bits
  • SMALLINT pour les valeurs entières 16 bits
  • NUMERIC(decimales, précision) pour une valeur numérique flottante
  • DATE pour une date
  • CHARACTER(taille) pour des caractères
Pour envoyer cette requête vers le Serveur:
  • nous utilisons un tIbDataBase qui assurera la connection vers le Serveur
  • nous utilisons un tIbSql
    • nous le relions à tIbDatabase
    • nous plaçons la requête SQL dans sa propriété IbSql.SQL (via l'Inspecteur ou en code)
    • nous appelons tIbSql.ExecQuery
  • la création n'est visible par tout le monde que si la transaction qui est utilisée pour la création de la table est confirmée


En Interbase, toutes les requêtes sont créées dans le cadre d'une transaction. Les transaction sont un mécanisme qui garantit que plusieurs sont réalisées en entier ou annulées. L'archétype est le transfert bancaire: si nous débitons DUPOND pour créditer MARTIN, le système doit garantir que soit les deux modifications sont réalisée ou aucune ne l'est.

En Delphi, les composants de bases de données utilisent par défaut des transactions transparentes pour le programmeur, mais nous pouvons gérer les transactions nous-même. C'est ce qui est recommandé pour Interbase.

En InterbaseExpress, nous utilisons un composant tIbTransaction que nous connectons à tIbDatabase.DefaultTransaction. Les primitives sont:

  • tIbTransaction.StartTransaction pour démarrer une nouvelle transaction avant une ou plusieurs opérations
  • tIbTransaction.Commit pour confirmer la suite d'opération, ou tIbTransaction.RollBack pour tout annuler.
  • StartTransaction et Commit ou RollBack sont souvent utilisés dans TRY EXCEPT:
          TRY
            IbTransaction1.StartTransaction;
            débite DUPOND
            crédite MARTIN
            IbTransaction1.Commit;
          EXCEPT
            IbTransaction1.RollBack;
          END;

Nous ne pouvons appeler IbTransaction1.StartTransaction si la transaction attachée à IbTransaction1 est fermée (committed ou Rolledback). Pour savoir si une transaction est active, nous pouvons utiliser la fonction InTransaction. Ainsi:

          IF NOT IbTransaction1.InTransaction
            THEN IbTransaction1.StartTransaction;

Que se passerait-il si nous réalisons le traitement sans cette IbTransaction:

  • pendant l'exécution de notre application d'autres applications (l'explorateur de bases de données, un autre de nos exe) ne "verraient" pas la table
  • un autre IbQuery de notre propre application pourrait ne pas voir la table
  • lorsque l'EXE sera fermé, la transaction sera automatiquement fermée
Le plus simple est donc d'utiliser Commit.



Voici à présent l'application:
   créez une nouvelle application et appelez-la "net_ibx_create_table"
   placez un tIbDataBase sur la Forme. Cliquez deux fois sur IbDataBase1, renseignez "local", "DataBase", "User Name" "Pass Word" et "Login Prompt".

Vérifiez la connection en cliquant "Test", puis fermez l'Editeur de Connection en cliquant "OK". La connection sera ouverte avant l'envoi de la requête

   placez un tIbTransaction sur la Forme, et reliez IbDatabase1.DefaultTransaction
   placez un tIbSql sur la tForme

   sélectionnez sa propriété DataBaseName et initialisez-la à

    IbDataBase1

   placez un tButton sur la Forme et créez sa méthode OnClick. Placez-y les instructions de création:

procedure TForm2.create_table_Click(SenderTObject);
  begin
    with IbSql1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add('CREATE TABLE 'k_table_name);
        Add('  ('
            +'    f_numero INTEGER,');
        Add('     f_nom CHAR(25),');
        Add('     f_jours SMALLINT,');
        Add('     f_prix NUMERIC(5, 2)');
        Add('   )');
      end// with Sql

      Try
        IbDatabase1.Open;

        display(IbDatabase1.DefaultTransaction.Name);

        if IbDatabase1.DefaultTransaction.Active
          then display('active')
          else display('closed');

        display('Commit_previous');

        if ibtransaction1.InTransaction
          then ibTransaction1.Commit;

        display('StartTransaction');
        ibtransaction1.StartTransaction;

        if IbDatabase1.DefaultTransaction.Active
          then display('active')
          else display('closed');

        display('Exec');
        ExecQuery;

        display('Commit');
        ibtransaction1.Commit;

        display('  ok');
      except
        on eException do
          display('  *** pb_create 'e.Message);
      end;
    end// with IbSql1
  end// create_database_Click


   compilez, exécutez, et cliquez le bouton


Vous pouvez télécharger le sources du projet "ib_create_table.zip".



5.1 - Vérifier la création

Nous pouvons vérifier que la création a été effectuée en utilisant l'explorateur de bases de données Delphi, ou en lisant les données ce cette table dans notre application.

Pour lire les données il suffit d'envoyer la requête

SELECT * FROM formations_3

au moteur. Nous verrons cette requête SELECT en détail plus bas, mais voici comment procéder pour notre test:
   ajoutez un composant tIbQuery sur la tForme
   sélectionnez sa propriété DataBaseName et initialisez-la à

    IbDataBase1

   placez un second tButton sur la Forme et placez-y la requête de lecture:

procedure TForm2.select_Click(SenderTObject);
  begin
    with IbQuery1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add('SELECT * FROM 'k_table_name);

        Try
          Open;
        except
          on eException do
            display('  *** pb 'e.Message);
        end;
      end// with Sql
    end// with IbQuery1
  end// select_Click


   compilez, exécutez, et cliquez le bouton


5.2 - Effacer une table

Pour supprimer une Table, il faut exécuter la requête:

DROP TABLE formations_3

Donc:
   placez un autre tButton sur la Forme et placez-y la requête de suppression:

procedure TForm2.drop_Click(SenderTObject);
  begin
    IbDatabase1.Open;
 
    with IbSql1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add('DROP TABLE 'k_table_name);
      end// with Sql

      Try
        if ibtransaction1.InTransaction
          then ibTransaction1.Commit;

        ibtransaction1.StartTransaction;
        ExecQuery;
        ibtransaction1.Commit;
        display('  ok');
      except
        on eexception do
           display('  *** pb_drop 'e.Message);
      end;
    end// with IbSql1
  end// drop_Click


   compilez, exécutez, et cliquez le bouton
Notez que:
  • nous avons utilisé un IbSql pour les requêtes qui modifient les données et un IbQuery `pour la lecture. La raison est que IbSql en fait que faire transiter la requête vers le moteur, alors que IbQuery tamponnne les résultats provenant du Serveur
  • notez toutefois, que pour envoyer une requête de modification il faut utiliser soit tIbsql.ExecQuery ou tIbQuery.ExecSql, et pour la lecture c'est tIbQuery.Open.

    tIbQuery.Open est équivalent à tIbQuery1.Active:= True (mais pas à ExecSql). Comme l'Inspecteur propose Active (pour pouvoir positionner ses éléments visuels), nous pouvons ouvrir une Table depuis l'Inspecteur, mais nous ne pouvons pas créer de Table en mode conception (il faut exécuter du code)



Vous pouvez télécharger le source du projet "net_ibx_create_table.zip".



Dans l'article Interbase Tutorial vous trouverez des exemple pour ajouter plusieurs tables à partir d'un schéma placé dans un fichier .TXT. Ibx.Net offre aussi un tout nouveau composant tIbScript.




6 - Ajouter des Données

6.1 - Ajout simple

Ajoutons un enregistrement pour le stage

    3, Interbase Delphi

L'instruction SQL est:

 INSERT INTO formations_3
     (f_numero, f_nom)
     VALUES (3, 'Interbase Delphi')

L'ajout d'enregistrement va modifier les données du Serveur, donc nous utiliserons tIbSql.ExecQuery ou tIbQuery.ExecSql.

De façon détaillée:
   créez une nouvelle application et nommez-la "ib_insert_data"
   placez un tIbTransaction sur la Forme
   placez un tIbDataBase sur la Forme. Cliquez deux fois sur IbDataBase1, renseignez "local", "DataBase", "User Name" "Pass Word" et "Login Prompt".
Vérifiez la connection en basculant IbDataBase1.Connected sur True, puis fermez la connection.
Sélectionnez DefaultTransaction et initialisez-la à IbTransaction1
   placez un tIbSql sur la tForme
   sélectionnez sa propriété DataBaseName et initialisez-la à IbDataBase1
   placez un tButton sur la Forme et créez sa méthode OnClick. Placez-y les instructions d'ajout:

procedure TForm2.insert_data_Click(SenderTObject);
    // -- hard coded values
  begin
    with IbSql1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add('INSERT INTO 'k_table_name);
        Add('  (f_numero, f_nom)');
        Add('  VALUES (3, ''Delphi Interbase'')');
      end// with Sql

      display_strings(Sql);

      Try
        IbDatabase1.Open;

        if ibtransaction1.InTransaction
          then ibTransaction1.Commit;

        ibtransaction1.StartTransaction;

        ExecQuery;

        ibtransaction1.Commit;

        display('  ok');
      except
        on eException do
          display('  *** pb_create 'e.Message);
      end;
    end// with IbSql1
  end// insert_data_Click

   compilez, exécutez, et cliquez le bouton


Pour avoir un peu plus de données nous avons ajouté une procédure qui insère quelques lignes à la fois.

La procédure qui effectue cet ajout est la suivante:

procedure TForm2.insert_many_Click(SenderTObject);
    // -- insert several hard coded values in a row

  procedure insert_generic(p_numberIntegerp_nameStringp_daysIntegerp_costDouble);
    begin
      with Form2IbSql1 do
      begin
        IbDatabase1.Open;

        Close;

        with Sql do
        begin
          Clear;
          Add('INSERT INTO 'k_table_name);
          Add('  (f_numero, f_nom, f_jours, f_prix)');
          DecimalSeparator:= '.';
          Add('  VALUES ('IntToStr(p_number)+ ', 'QuotedStr(p_name)
              + ', 'IntToStr(p_days)+ ', 'FloatToStr(p_cost)+ ')');
          DecimalSeparator:= ',';
        end;

        display_strings(Sql);

        Try
          if not IbTransaction1.InTransaction
            then IbTransaction1.StartTransaction;
          ExecQuery;
          IbTransaction1.Commit;
          display('  ok');
        except
          on eException do
            display('  *** pb_insert 'e.Message);
        end;
      end// with IbSql1
    end// insert_generic

  begin //  // insert_automatic_Click
    IbDatabase1.Open;

    insert_generic(1, 'Initiation Delphi', 3, 1400.40);
    insert_generic(2, 'Bases de Données Delphi', 3, 1400);
    insert_generic(3, 'Interbase Delphi', 3, 1400);
    insert_generic(4, 'Composants Delphi', 3, 1400);
    insert_generic(5, 'UML et Patterns en Del', 3, 1400);
    insert_generic(6, 'Initiation Pascal', 4, 1900);
  end// insert_many_Click



Nous avons ajouté l'effacement dans la foulée. Pour effacer l'enregistrement ayant le numéro 8, nous exécutons une requête

 DELETE
     FROM formations_3
     WHERE f_numero= 8

En détail:
   placez un tButton sur la Forme et créez sa méthode OnClick. Placez-y les instructions de modification:

procedure TForm2.delete_all_Click(SenderTObject);
  begin
    with IbSql1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add('DELETE FROM 'k_table_name);
        Add('  WHERE f_numero= 3');
      end// with Sql

      Try
        IbDatabase1.Open;

        if ibtransaction1.InTransaction
          then ibTransaction1.Commit;

        ibtransaction1.StartTransaction;

        ExecQuery;

        ibtransaction1.Commit;

        display('  ok');
      except
        on eException do
          display('  *** pb_create 'e.Message);
      end;
    end// with IbSql1
  end// delete_all_Click

   compilez, exécutez, et cliquez le bouton


L'application en pleine action a l'allure suivante:



Vous pouvez télécharger les sources du projet "net_ibx_insert_data_3.zip.



Dans l'article Interbase Tutorial vous trouverez aussi des exemple pour généraux pour ajouter des données en mode "batch".



Mentionnons que le projet m'a donné un peu de fil à retordre:

  • j'étais parti du projet précédent (pour éviter la frappe des chemins divers)
  • la sauvegarde du projet sous un nouveau nom s'est bien passée
  • la sauvegarde de l'unité se fait apparemment dans son répertoire d'origine (et non pas dans celui du .DPR sauvegardé auparavant)
  • j'avais peut être aussi laissé traîner un autre projet
  • et pour couronné le tout j'ai mal effacé le bouton "drop_table_". Il m'a fallu un quart d'heure pour reprendre la main
  • puis j'ai eu une succession de:

        "object reference not set to an instance of an object"

    A tout hasard, j'ai forcé les fermetures des requêtes avant de quitter l'application, et cela se passait un peu mieux

  • finalement j'ai fait deux ou trois erreurs dans mes requêtes SQL. Après correction de l'erreur, fermeture de Delphi et rechargement du tout, le problème disparaît. Cela me rappelle le temps de Delphi 1 et Windows 3.11. On n'arrête pas le progrès



7 - Lire et Afficher

7.1 - 5.1- Principe

Pour afficher un enregistrement, nous devons d'abord récupérer ses valeurs du Serveur.

Pour lire les données contenues dans une table, SQL utilise l'instruction SELECT. Par exemple:

 SELECT f_numero, f_nom
     FROM formations_3

Lorsque le Serveur reçoit cette requête:

  • il vérifie sa syntaxe
  • il construit une table contenant les valeurs demandées
  • ces données sont envoyées au Client
Plus concrètement:
   créez une nouvelle application et appelez-la "net_ibx_select"
   placez un tIbTransaction sur la Forme
   placez un tIbDataBase sur la Forme. Cliquez deux fois sur IbDataBase1, renseignez "local", "DataBase", "User Name" "Pass Word" et "Login Prompt".
Vérifiez la connection en basculant IbDataBase1.Connected sur True, puis fermez la connection.
Sélectionnez DefaultTransaction et initialisez-la à IbTransaction1
   placez un tIbQuery sur la tForme
   sélectionnez sa propriété DataBaseName et initialisez-la à IbDataBase1
   placez un tButton sur la Forme et créez sa méthode OnClick. Placez-y les instructions de lecture:

procedure TForm2.select_Click(SenderTObject);
  begin
    with IbQuery1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add('SELECT * FROM 'k_table_name);

        Try
          Open;
        except
          on eException do
            display('  *** pb 'e.Message);
        end;
      end// with Sql
    end// with IbQuery1
  end// select_Click

   compilez, exécutez, et cliquez le bouton


Vous pouvez télécharger le source du projet "net_ibx_select.zip".



7.2 - Comment ça Marche

Lorsque nous exécutons IbQuery1.Open:
  • Delphi envoie la requête SELECT au Serveur
  • celui-ci construit une table résultat, en utilisant, bien sûr, la table FORMATIONS, mais aussi éventuellement des tables annexes (index, contraintes etc.).

  • cette table résultat est envoyée via le réseau au Client Interbase. Celui ci la transmet ensuite à l'application. Delphi place alors ce résultat dans un tampon mémoire associé à tIbQuery:



7.3 - Affichage

Une fois que IbQuery a récupéré les données nous pouvons les afficher ou les traiter en mémoire.

Pour afficher les données nous utilisons:

  • un tDataSource qui récupère les données du tIbQuery
  • un ou plusieurs composants d'affichage relié au tDataSource. Par exemple un tDbGrid.
Par conséquent:
   sélectionnez dans la page "Data Access" de la Palette le composant tDataSource:

et placez le sur la Forme

   sélectionnez dans la page "Data Controls" de la Palette le composant tdbGrid:

et placez le sur la Forme

   sélectionnez sa propriété DataSource et donnez-lui la valeur DataSource1

   compilez, exécutez, et cliquez le bouton qui lance la requête


7.4 - Affichage en mode conception

Nous pouvons aussi lancer la requête de lecture en mode conception. Il faut pour cela que:
  • tIbDatabase soit correctement initialisé
  • tIbQuery soit relié à tIbDatabase
  • la propriété tIbQuery.Sql soit initialisée en utilisant l'Inspecteur
  • la requête soit envoyée en basculant tIbQuery.Active sur True
Donc:
   sélectionnez IbQuery1
   cliquez sur sa propriété Sql
   Delphi ouvre l'éditeur de Sql. A présent les tables créées sont affichées:

?? <IMG SRC="_i_image-ibquery_sql_editor.png" align=middle>

   sélectionnez la table "formation"
   les colonnes de cette table sont affichées

   sélectionnez les colonnes que vous souhaitez afficher (ou "*")

   fermez l'éditeur de requête
   sélectionnez Active, et basculez sa valeur sur True
   Delphi affiche les valeurs de la table


7.5 - SELECT

 SELECT est la seule instruction de lecture de données du Serveur. Sa structure générale est:

 SELECT colonnes
      FROM tables
      WHERE conditions

et:

  • colonnes indique quelles colonnes nous voulons voir figurer dans le résultat. Nous pouvons
    • citer explicitement les colonnes souhaitées, dans l'ordre qui nous convient:

       SELECT f_nom, f_numero
            FROM formations

      Nous pouvons ne demander qu'une partie des colonnes (projection)

       SELECT f_nom
            FROM formations

      L'abréviation "*" permet de désigner "toutes les colonnes"

       SELECT *
            FROM formations

    • effectuer des sommes, des moyennes (agrégats)

       SELECT COUNT(*)
            FROM formations

      le résultat est alors une table d'une ligne, une colonne avec le nombre de formations

  • tables contient le noms des tables à utiliser pour calculer le résultat. Par exemple:

     SELECT *
          FROM formations, dates
          WHERE f_nom='UML ET DELPHI'

  • conditions permet
    • de ne retenir que certaines lignes du résultat. Par exemple

       SELECT *
            FROM dates
            WHERE f_date> '2004/05/01'

    • de trier le résultat:

       SELECT *
            FROM dates
            ORDER BY f_date

Ce qu'il faut bien comprendre est que:
  • SELECT calcule un résultat A PARTIR de tables, mais que le résultat n'EST PAS les tables. Lorsque nous demandons une somme ou une moyenne, par exemple, SELECT retourne un nombre.
  • Certes, "SELECT * FROM formations" retourne bien les mêmes données que celle de la table sur disque "formations". Mais ce n'est qu'un instantané réalisé lorsque la requête a été lancée. Il s'agit d'une copie. Si un autre utilisateur ajoute une nouvelle formation la copie que nous avons dans le cache attaché à IbQuery ne le reflète pas
  • pour rafraîchir notre cache, la SEULE façon de faire est de relancer la requête (en fermant et réouvrant tIbQuery)



8 - Modifier des Données

8.1 - Principe

Supposons que notre table FORMATIONS contienne les valeurs suivantes:

Pour changer le libellé "Interbase Delphi" en "Interbase" nous utilisons une requête UPDATE:

 UPDATE formations
     SET f_nom= 'Interbase'
     WHERE f_numero= 8

Cette requête qui modifie les données du Serveur est envoyée vers le Serveur en utilisant tIbSql1.ExecQuery out tIbQuery1.ExecSql



En détail:
   créez une nouvelle application "p_net_ibx_update"
   placez un tIbTransaction sur la Forme
   placez un tIbDataBase sur la Forme. Cliquez deux fois sur IbDataBase1, renseignez "local", "DataBase", "User Name" "Pass Word" et "Login Prompt".
Vérifiez la connection en basculant IbDataBase1.Connected sur True, puis fermez la connection.
Sélectionnez DefaultTransaction et initialisez-la à IbTransaction1
   placez un tIbSql sur la tForme
   sélectionnez sa propriété DataBaseName et initialisez-la à IbDataBase1
   placez un tButton sur la Forme et créez sa méthode OnClick. Placez-y les instructions de modification:

procedure TForm2.update_data_Click(SenderTObject);
  begin
    with IbSql1 do
    begin
      Close;

      with Sql do
      begin
        Clear;
        Add(sql_edit_.Text);
      end;

      Try
        ExecQuery;
        display('  ok');
      except
        on e:exception do
          display('< *** pb_update 'e.Message );
      end;
    end// with IbSql
  end// update_data_Click

   compilez, exécutez, et cliquez le bouton


Vous pouvez télécharge le source du projet "net_ibx_update.zip".



8.2 - La clause WHERE

Dans l'instruction précédente nous avons spécifié la valeur f_numero à l'aide de WHERE.

Que se passerait-il si nous envoyons:

 UPDATE formations
     SET f_nom= 'Interbase'

Eh bien le Serveur modifierait le nom de TOUS les enregistrements.

Si nous souhaitons limiter les modifications à certaines lignes, il est impératif:

  • que chaque ligne de chaque table ait un identificateur unique pour que nous puissions désigner cette ligne en cas de modification
  • que nous indiquions dans UPDATE les lignes à modifier
Si en revanche nous souhaitons modifier plusieurs lignes à la fois, nous pouvons :
  • omettre WHERE. Par exemple, pour passer tous les noms en majuscule:

     UPDATE formations
         SET f_nom= UPPER(f_nom)

  • changer plusieurs lignes satisfaisant une condition. Pour effectuer une réduction promotionnelle de 5% sur les prix inférieurs à 1400 euros :

     UPDATE formations
         SET f_prix= f_prix* 0.95
         WHERE WHERE f_prix<= 1400.00

    Toutefois:

    • ne répétez pas cette requête de réduction trop souvent: il faut bien que je mange un peu !
    • nous faisons des conditions tarifaires particulières (groupes, formations intra, étudiant, particulier, réinsertion...), que nous sommes prêts à vous présenter si vous me téléphonez directement à l'Institut Pascal au 01.42.83.69.36.
Il est donc fondamental de bien comprendre qu'un UPDATE sans clause WHERE porte sur tous les enregistrements.



8.3 - UPDATE et AFFICHAGE

Ce fonctionnement de UPDATE est particulièrement important lorsque nous modifions un enregistrement affiché à l'écran dans un dbGrid: nous pensons que Interbase sait que nous "modifions l'enregistrement courant". Or ce concept d'enregistrement courant n'existe pas en mode SQL:
  • le dbGrid affiche le résultat obtenu par une requête SELECT
  • or SELECT calcule un résultat "instantané". Nous avons vu que SELECT peut supprimer des colonnes (projection), retirer des lignes (filtrage), effectuer des moyennes ou calculer un résultat à partir de plusieurs tables.

    Le résultat du calcul est envoyé par le Serveur vers le Client, et le Serveur ne garde plus aucune trace de ce qu'il a envoyé. Un autre utilisateur peut même modifier les tables sans que notre Client en soit informé

  • par conséquent toute modification du résultat ne pourait être que local.
  • en fait par défaut le résultat est non-modifiable (ReadOnly). Et si nous essayons de taper une nouvelle valeur au clavier, Delphi refuse de modifier le champ du dbGrid.
La seule façon de modifier une valeur affichée de façon interactive est de déclencher une requête UPDATE en utilisant un composant tIbUpdateSql. Le plus simple pour synchroniser les modifications est d'utiliser un composant tIbUpdateSql.



8.4 - tIbUpdateSql

Ce composant a pour vocation de contenir la requête SQL qui doit être exécutée lorsque le tIbQuery doit être modifié. Cette requête est placée dans tIbUpdateSql.ModifySql.

Automatisons par exemple la mise à jour de f_nom lorsque nous tapons une valeur dans un tDbGrid:
   créez une nouvelle application et appelez-la "p_net_ibx_update_sql"
   placez un tIbTransaction sur la Forme
   placez un tIbDataBase sur la Forme. Cliquez deux fois sur IbDataBase1, renseignez "local", "DataBase", "User Name" "Pass Word" et "Login Prompt".
Vérifiez la connection en basculant IbDataBase1.Connected sur True, puis fermez la connection.
Sélectionnez DefaultTransaction et initialisez-la à IbTransaction1
   placez un tIbQuery sur la tForme
  • sélectionnez sa propriété DataBaseName et initialisez-la à IbDataBase1
  • sélectionnez sa propriété Sql et placez-y la requête

     SELECT *
          FROM formations

Vous pouvez aussi utiliser l'Editeur de Requête en cliquant sur l'ellipse ... de Sql:

   ajoutez un composant tDataSource
  • sélectionnez DataSet et donnez-lui la valeur IbQuery1
   reliez DataSource1 à un tDbGrid:
  • placez un tdbGrid de sur la Forme
  • sélectionnez sa propriété DataSource et reliez la à DataSource1
   ouvrez IbQuery1 en basculant Active sur True
   ajoutez un tIbUpdateSql:
  • sélectionnez la page "Interbase" de la Palette, sélectionnez le composant tIbUpdateSql et posez-le sur la Forme
  • connectez le IbQuery1 et IbUpdateSql:
    • en initialisant IbQuery1.UpdateObject avec IbUpdateSql1
    • en basculant IbQuery1.CachedUpdate à True
  • sélectionnez sa propriété IbUpdateSql1.ModifySql, cliquez sur l'ellipse pour ouvrir l'éditeur de ModifySql (c'est un éditeur de tStrings). Delphi y a placé la requête par défaut:


   compilez, exécutez:
  • Sélectionnez dbGrid1, tapez une valeur dans la colonne F_NOM.
  • Notez bien que le dbGrid permet à présent la modification de valeurs (alors que sans tIbUpdateSql ces modifications étaient impossibles).
  • lorsque nous quittons la ligne (en changeant de composant, ou en changeant de ligne dans le dbGrid), la requête de modification est envoyée vers le Serveur


Notez que:

  • Vous pouvez aussi utiliser l'Editeur de IbUpdateSql1 en cliquant deux fois sur ce composant. Delphi propose alors:

    Et si nous confirmons en cliquant "Generate Sql", Delphi va générer les codes pour l'ajout, la modification et l'effacement:

  • pour désigner les valeur des champs à utiliser, nous avons employé une requête paramétrée, en désignant les paramètres par le nom du champ:

              f_nom= :f_nom

  • nous aurions pu modifier plusieurs colonnes

     UPDATE formations
         SET f_nom= :f_nom, f_jours:= :f_jour, f_prix= :f_prix
         WHERE f_numero= :f_numero



Vous pouvez télécharger le projet "net_ibx_update_sql.zip".



8.5 - "Old" values

Nous avons utilisé f_numero pour identifier la ligne à modifier. Mais que se passe-t-il si nous souhaitons modifier la clé elle-même ? En effet :f_numero désigne la valeur actuelle, qui est la valeur modifiée, et non pas la valeur qui permet de désigner la ligne dans la table.

Pour résoudre ce problème, Delphi a crée le concept des "old_values", correspondant à la valeur que le champ avait lors de la lecture de la table. Et le paramètre pour désigner la valeur se note :old_f_numero

Si nous souhaitons pouvoir modifier tous les enregistrements, nous utilisons donc dans tIbUpdateSql.ModifySql une requête du type:

 UPDATE formations
     SET f_numero= :f_numero, f_nom= :f_nom
     WHERE f_numero= :old_f_numero

Ce concept de "old values" est fondamental pour la mise à jour concurrente que nous présenterons voir ci-dessous.




9 - Télécharger les Exemples

Voici les programmes utilisés dans cet article et que vous pouvez télécharger:

Les .ZIP comprennent:
  • le .DPR, la forme principale, les formes annexes eventuelles
  • les fichiers de paramètres (le schéma et le batch de création)
  • dans chaque .ZIP, toutes les librairies nécessaires à chaque projet (chaque .ZIP est autonaume)
Ces .ZIP contiennent des chemins RELATIFS. Par conséquent:
  • créez un répertoire n'importe où sur votre machine
  • placez le .ZIP dans ce répertoire
  • dézippez et les sous-répertoires nécessaires seront créés
  • compilez et exécutez
Ces .ZIP ne modifient pas votre PC (pas de changement de la Base de Registre, de DLL ou autre). Pour supprimer le projet, effacez le répertoire.



Comme d'habitude:

  • nous vous remercions de nous signaler toute erreur, inexactitude ou problème de téléchargement en envoyant un e-mail à jcolibri@jcolibri.com. Les corrections qui en résulteront pourront aider les prochains lecteurs
  • tous vos commentaires, remarques, questions, critiques, suggestion d'article, ou mentions d'autres sources sur le même sujet seront de même les bienvenus à jcolibri@jcolibri.com.
  • plus simplement, vous pouvez taper (anonymement ou en fournissant votre e-mail pour une réponse) vos commentaires ci-dessus et nous les envoyer en cliquant "envoyer" :
    Nom :
    E-mail :
    Commentaires * :
     

  • et si vous avez apprécié cet article, faites connaître notre site, ajoutez un lien dans vos listes de liens ou citez-nous dans vos blogs ou réponses sur les messageries. C'est très simple: plus nous aurons de visiteurs et de références Google, plus nous écrirons d'articles.



10 - Conclusion

Lors de cette présentation de dbExpress, nous avons indiqué comment installer Interbase, créer une base, des tables, ajouter, lire, modifier et effacer des données.

Si vous avez des questions, vous pouvez:

  • vous reporter au livre Delphi dBase qui présente, par le détail, la gestion des composants visuels et les techniques de traitement des données (formatage, vérfications, calculs...)
  • pour les blobs, voyez Blobs Interbase
  • pour l'utilisation d'Interbase en mode Client Serveur, sans utiliser le BDE, voyez le Tutorial Interbase
  • la présentation Architecture du Moteur Interbase présente l'organisation du programme Interbase, correspondant aux sources fournies par Borland pour la version 6.
  • je présenterai à la conférence Borcon France 2004 le panorama des techniques d'accès aux données Interbase: les API isc, le BDE, Interbase Express, dbExpress, et pour Delphi 8, IBX.NET en mode VCL.NET et ADO.NET en mode Windows Forms.
  • vous pouvez aussi m'adresser vos questions par e-mail à jcolibri@jcolibri.com
Nous n'avons pas essayé d'être exhaustif dans la présentation. Lors des stages que j'anime personnellement à l'Institut Pascal, j'entre beaucoup plus dans le détail:
  • la gestion des multiples erreurs et exceptions qui interviennent lors d'applications utilisant des bases de données
  • les possibilités d'installer Interbase depuis Delphi, et d'interroger les paramètres de la Base ou du schéma depuis un programme Delphi, de lister les tables, les champs etc
  • le traitement des contraintes (clé primaires, intégrité référentielle, intégrité sémantique)
  • la manipulation détaillée des valeurs extraite d'une Table, en utilisant les tFields et les différents composants visuels tDb_xxx, ainsi que les traitements spécifiques aux chaînes, aux dates, aux blobs
  • les techniques de validation de saisie essentielles pour toute application de gestion
  • le traitement spécifiques à dbExpress:
    • l'utilisation de tClientDataset avec ses multiples possibilités
    • les paramétrage du tDatasetProvider
    • la gestion des erreurs de réconciliation et le traitement d'utilisateurs multiples
  • l'étude approfondie du langage SQL, qui est au coeur de tout traitement avec des Serveurs Sql
  • les triggers, les procédures cataloguées (tStoredProc), les générateurs
  • la gestion de Serveur (sauvegarde / restauration, statistiques, réglage)
Pour examiner le programme détaillé de cette formation, cliquez Client Serveur Interbase. Nous proposons de plus d'autres formations présentées dans ces pages (programme, dates des prochaines sessions, conditions, transparents, abonnement à la lettre d'information...).

Finalement j'interviens aussi pour des missions d'audit, de réalisation de projet, de portage et maintenance, et de tutorat.




11 - L'auteur

John COLIBRI est passionné par le développement Delphi et les applications de Bases de Données. Il a écrit de nombreux livres et articles, et partage son temps entre le développement de projets (nouveaux projets, maintenance, audit, migration BDE, migration Xe_n, refactoring) pour ses clients, le conseil (composants, architecture, test) et la formation. Son site contient des articles avec code source, ainsi que le programme et le calendrier des stages de formation Delphi, base de données, programmation objet, Services Web, Tcp/Ip et UML qu'il anime personellement tous les mois, à Paris, en province ou sur site client.
Created: jan-04. Last updated: mar-2020 - 250 articles, 620 .ZIP sources, 3303 figures
Contact : John COLIBRI - Tel: 01.42.83.69.36 / 06.87.88.23.91 - email:jcolibri@jcolibri.com
Copyright © J.Colibri   http://www.jcolibri.com - 2001 - 2020
Retour:  Home  Articles  Formations  Développement Delphi  Livres  Pascalissime  Liens  Download
l'Institut Pascal

John COLIBRI

+ Home
  + articles_avec_sources
    + bases_de_donnees
      + programmation_oracle
      + interbase
        – interbase_blobs
        – interbase_tutorial
        – interbase_dbexpress
        – interbase_ibx_net
        – ib_dbexpress_net
        – delphi_8_ado_net
        – borland_data_provider
        – sql_script_extraction
        – interbase_udf
        – sql_script_executer
        – ib_blob_extraction
        – insert_blob_script
        – ib_stored_procedures
      + sql_server
      + firebird
      + mysql
      + xml
      – paradox_via_ado
      – mastapp
      – delphi_business_objects
      – clientdataset_xml
      – data_extractor
      – rave_report_tutorial
      – visual_livebindings
      – migration_bde
    + web_internet_sockets
    + services_web_
    + prog_objet_composants
    + office_com_automation
    + colibri_utilities
    + uml_design_patterns
    + graphique
    + delphi
    + outils
    + firemonkey
    + vcl_rtl
    + colibri_helpers
    + colibri_skelettons
    + admin
  + formations
  + developpement_delphi
  + présentations
  + pascalissime
  + livres
  + entre_nous
  – télécharger

contacts
plan_du_site
– chercher :

RSS feed  
Blog

Expert Delphi Résolution de problèmes ponctuels, optimisation, TMA Delphi, audit, migration, réalisation de projets, transfert de technologie - Tél 01.42.83.69.36
Formation Delphi 7 complete L'outil de développpement, le langage de programmation, les composants, les bases de données et la programmation Internet - 5 jours
Formation de Delphi 7 à Xe3 Présentation des nouveautés de Delphi 5, 6, 7 à Delphi Xe, Xe2, Xe3: nouveautés Rtl (génériques, anonymes, RTTI), Vcl (LiveBindings, FireMonkey, Mobiles), outil - 5 jours