Tutorial ORACLE - John COLIBRI. |
- résumé : réalisation d'applications Base de Données Client Oracle, avec connection au Serveur, création de Tables, ajout / lecture / modification de données
- mots clé : Client Oracle - CREATE TABLE, SELECT, INSERT, UPDATE,
dbExpress, DataSnap, modèle nomade, relation maître détail
- logiciel utilisé : Windows XP personnel, Delphi 6.0, Oracle 10g
- matériel utilisé : Pentium 1.400Mhz, 256 M de mémoire, 140 Giga disque dur
- champ d'application : Delphi 1 à 2005 sur Windows, Oracle
- niveau : développeur Delphi / Oracle
- plan :
1 - Introduction
Nous allons présenter ici comment gérer une application Client Oracle en utilisant les composants Delphi. Après la lecture de cet article, vous saurez: - créer une Table et ses indexes
- lire, écrire et modifier les données de cette table
- travailler en mode nomade (non connecté au Serveur)
- gérer plusieurs tables liées
2 - Vérification de l'Accès au Serveur Dans les articles précédents, nous avons présenté:
Nous utiliserons les paramètres par défaut Oracle classiques:
- nom d'utilisateur: SCOTT
- mot de passe: TIGER
Si votre administrateur vous a fourni d'autres noms d'utilisateur / mot de passe, vous remplacerez SCOTT/TIGER par vos valeurs.
Si vous utilisez une base déjà installée, voici comment vérifier que vous arrivez bien à communiquer avec votre Serveur Oracle: - si vous travaillez directement sur le PC sur lequel est installé le Serveur:
| chargez l'outil graphique SqlPlus (démarrer | Programmes | OraDb10g_home1 | Application Development | Sql Plus)
| | Sql-Plus nous demande qui nous sommes
| | nous tapons SCOTT, TIGER et ORCL puis cliquons "OK" |
| Sql-Plus nous accueille: |
| nous affichons la table EMP (ou n'importe quelle autres requête correspondant à une table) SELECT * FROM emp; Entrée
| | Oracle répond |
Notez que "Host String" correspond au paramètre qui se trouve dans "OracleHome"\NetWork\ADMIN\tnsnames.ora:
# tnsnames.ora Network Configuration File: C:\oracle\product\10.1.0\Db_1\network\admin\tnsnames.ora # Generated by Oracle configuration tools. ORCL = (DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = pol-1400)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = orcl)
) ) | - si vous souhaitez placer votre application sur le PC contenant le Client Oracle (ce qui est plus classique, mais oblige à utiliser 2 PC), depuis le
PC contenant le Client:
| sélectionnez "démarrer | programmes | OraClient10g_home1 | application Developpments | SQL Plus"
| | Sql-Plus nous demande qui nous sommes:
| | nous tapons SCOTT, TIGER et MY_NAME_RESOLUTION puis cliquons "OK" |
| Sql-Plus nous accueille: |
| nous affichons la table EMP (ou n'importe quelle autres requête correspondant à une table) SELECT * FROM emp; Entrée
| | le Serveur renvoie le contenu de cette table |
Notez que "Host String" correspond au paramètre qui se trouve dans
"OracleHome"/NetWork/ADMIN/tnsnames.ora: # tnsnames.ora Network Configuration File:
C:\oracle\product\10.1.0\Client_1\NETWORK\ADMIN\tnsnames.ora # Generated by Oracle configuration tools. MY_NAME_RESOLUTION = (DESCRIPTION = (ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = pol-1400)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME= ORCL)
) ) |
3 - Architecture de l'Application Client
Le fonctionnement Client / Serveur traditionnel est organisé avec un Serveur qui répond à plusieurs Clients, chacun situé sur des PC différents:
Prenons le cas d'un Client particulier: - lorsque ce Client souhaite communiquer avec le Serveur, il envoie une requête via le réseau:
- et le Serveur répond, en un ou plusieurs paquets:
Du côté du Client, nous avons les couches logicielles suivantes:
- au niveau le plus bas, le PC est équipé des couches réseau. La pile TCP/IP par exemple, qui est installée automatiquement par Windows:
- cette couche est attaquée par le Client Oracle (appelée jadis SqlNet) qui a été installée lors de l'installation Client Oracle:
- le Client Oracle est attaqué par les composants d'accès Delphi, qui communiqueront avec l'application utilisateur en utilisant les contrôles Delphi:
- et finalement l'application utilisateur (comptabilité, facturation, portail web pour un catalogue client etc):
Au niveau Delphi, les étapes d'une communication sont les suivantes: - le Client Delphi établit la connection
- puis, pour chaque requête:
- le Client envoie sa requête
- le Client récupère la réponse
- le Client ferme la connection
Ces trois étapes peuvent être réalisées par différents types de composants Delphi:
- le BDE (Borland Database Engine)
- les composants dbExpress
- des composants Ado (la mécanique Microsoft)
- des composants écrits spécialement pour gérer en Delphi des bases de
données Oracle
Nous utiliserons ici les composants dbExpress fournis avec Delphi. Ces composants comportent: - tSqlConnection qui sert à établir la connection avec le Serveur. C'est là
que nous fournissons les paramètres Oracle (SCOTT, TIGER, ORCL):
- SqlQuery qui permet d'envoyer des requêtes Sql vers le Serveur et qui
reçoit les réponses. C'est à ce niveau seul que nous envoyons les requêtes SQL. Nous pouvons d'ailleurs travailler avec ce niveau seul, pour écrire des données en mode batch par exemple.
- tDatasetProvider qui transforme les réponses du Serveur en paquets au format normalisé Delphi.
- tClientDataSet qui stocke en mémoire les données reçues du Serveur et permet des mise en forme de ces données (tri, filtrage, navigation, sauvegarde locale etc):
- tDataSource et tdbGrid (ou autres tdbEdit, tdbListbox ...) qui présentent les données à l'utilisateur et lui permettent de les modifier:
4 - La Connection à Oracle Voici comment ouvrir une connection depuis le Client:
| créez une nouvelle application Delphi, et nommez-la p_oracle_dbx_connect.dpr | |
dans la page dbExpress de la Palette sélectionnez SqlConnection: et posez ce composant sur la Forme | |
pour fournir les paramètres de login, double cliquez sur SqlConnection1 | | Delphi ouvre l'éditeur de connexion:
| | sélectionnez le pilote Oracle, et tapez les paramètres de connection (SCOTT, TIGER, ORCL):
Notez que ORCL est le nom qui apparaît dans votre fichier tnsnames.ora:
Ainsi, si nous nous étions connecté depuis le PC Client, nous aurions du utiliser MY_NAME_RESOLUTION au lieu de ORCL (cf le paragraphe 2 ci-dessus). Et vous aurez à utiliser votre nom figurant dans votre fichier tnsnames.ora. |
| fermez l'éditeur de connection | |
pour éviter d'avoir à taper sempiternellement SCOTT/TIGER, sélectionnez dans l'inspecteur d'objet LoginPrompt et basculez sa valeur sur False. Puis établissez la connection en basculant Connected sur True
| | au bout de quelques instants Connected bascule sur True, indiquant que la connection est effectivement établie.
Si tel n'était pas les cas, revoyez les étapes précédentes une à une. | | rebasculez Connected sur False. En effet les différents composants
Delphi forceront l'ouverture de la connection lorsqu'ils en auront besoin. | Vous pouvez télécharger cette application en cliquant oracle_dbx_connect.zip.
5 - Création de Tables Oracle 5.1 - Principe Nous allons créer une table contenant pour chaque formation: - un code (par exemple 8)
- un nom (par exemple "Delphi Oracle")
- un prix (par exemple 1.400)
Pour cela nous devons envoyer une requête en langage SQL vers le Serveur Oracle. La syntaxe de cette requête est:
CREATE TABLE formations
(f_numero INTEGER, f_nom CHARACTER(11), 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 Oracle et correspondant aux types SQL usuels citons: - les nombres:
- NUMERIC(decimales, précision) pour une valeur numérique flottante, avec 38 chiffres significatifs
- de nombreuses variantes (INTEGER, SMALLINT FLOAT, REAL ) existent, à la fois pour des raisons de portabilité et pour
améliorer le nombre de chiffres significatifs
- les chaînes de caractères:
- CHARACTER(taille) pour chaînes avec allocation fixe, taille maximale 2000 caractères
- NVARCHAR2(taille) pour les chaînes avec allocation dynamique, taille maximale 32.767 caractères
- les dates:
Pour envoyer cette requête vers le Serveur: - nous utilisons un tSqlConnection qui assurera la connection vers le Serveur
- nous utilisons un tSqlQuery
- nous le relions à tSqlConnection
- nous plaçons la requête SQL dans sa propriété tSqlQuery.SQL (via l'Inspecteur ou en code)
- nous appelons tSqlQuery.ExecSql
5.2 - Utilisation de SQL La requête à envoyer au Serveur est placée dans tSqlQuery.Sql. tSqlQuery.Sql est un descendant de tStrings. Nous pouvons donc utiliser, par exemple:
SqlQuery1.Sql.Add('CREATE TABLE formations (f_numero INTEGER, f_nom CHARACTER(11))');
| Pour construire la requête: - nous pouvons utiliser Add pour ajouter une ligne de requête, Text pour affecter une requête, Clear pour purger tout texte antérieur, ou même
LoadFromFile pour lire un fichier .txt contenant la requête:
SqlQuery1.Sql.LoadFromFile('cree_formation.txt'); |
La mise en page n'a aucune importance pour le Serveur: la requête peut être répartie en plusieurs lignes:
SqlQuery1.Sql.Add('CREATE TABLE');
SqlQuery1.Sql.Add(' formations ');
SqlQuery1.Sql.Add(' (f_numero INTEGER, f_nom CHARACTER(11))');
|
l_requete:= 'CREATE TABLE '+ Edit1.Text+ ' (';
l_requete:= l_requete+ Edit2.Text+ ')';
SqlQuery1.Sql.Add(l_requete); |
5.3 - Comment ça Marche Au niveau fonctionnement: Notez que l'envoi de toute requête qui modifie des données du Serveur (et la
création d'une nouvelle table est bien une modification) ne peut se faire que par du code (et non PAS en basculant SqlQuery1.Active sur True en mode conception)
5.4 - L'application Pour créer notre table
| créez une nouvelle application et appelez-la "p_oracle_dbx_create_table.dpr" | |
ajoutez un tSqlConnection sur la Forme (comme détaillé ci-dessus): - dans la page "dbExpress" de la Palette, sélectionnez SqlConnection et posez-le sur la Forme
- double cliquez pour ouvrir l'éditeur de connection, sélectionnez ORACLE puis remplissez SCOTT/TIGER/ORCL
- dans l'Inspecteur d'Object, basculez LoginPrompt sur False
- vérifiez la connection en basculant Connected sur True, puis rebasculez la valeur sur False
| |
sélectionnez dans la page "dbExpress" de la Palette le composant SqlQuery: | |
sélectionnez sa propriété SqlConnection et initialisez-la à SqlConnection1 | |
placez un tButton sur la Forme et créez sa méthode OnClick. Placez-y les instructions de création: |
procedure TForm1.create_table_Click(Sender: TObject);
begin with SqlQuery1 do
begin Close;
with Sql do begin
Clear; Add('CREATE TABLE formations');
Add(' ('
+' f_numero INTEGER,');
Add(' f_nom CHAR(23),');
Add(' f_jours SMALLINT,');
Add(' f_prix NUMERIC(5, 2)');
Add(' )');
end; // with Sql Try
SqlConnection1.Open; ExecSql;
except
on e: Exception do
begin
display(' *** pb_create '+ e.Message);
end; end;
end; // with SqlQuery1 end; // create_table_Click |
| compilez, exécutez, et cliquez le bouton |
Vous pouvez télécharger le sources du projet "ib_dbx_create_table.zip".
5.5 - Effacer une table Pour supprimer une Table, il faut exécuter la requête:
Donc:
| placez un autre tButton sur la Forme et placez-y la requête de suppression: |
procedure TForm1.drop_table_Click(Sender: TObject);
begin with SQLQuery1 do
begin Close;
with Sql do begin
Clear; Add('DROP TABLE formations');
Try ExecSql;
except
on e: Exception do
display(' *** pb '+ e.Message);
end; end; // with Sql
end; // with SQLQuery1 end; // drop_table_Click |
| compilez, exécutez, et cliquez le bouton |
Notez que:
- nous avons le même SqlQuery en changeant le contenu de sa propriété SQL. Nous aurions aussi bien pu utiliser des SqlQuery séparés.
5.6 - Vérifier la création
Nous pouvons vérifier que la création d'une table a été effectuée - soit en exécutant DROP TABLE: si la table n'existe pas, le Serveur Oracle provoquera une exception.
- soit en exécutant SELECT * FROM formations, que nous allons présenter ci-dessous
- soit en exécutant SELECT * FROM user_tables qui affiche toutes les
tables de SCOTT/TIGER. Nous allons présenter SELECT ci-dessous
5.7 - Création de deux autres tables Ajoutons deux autres tables à notre exemple: une table pour les lieux des formation, et une table pour les dates.
Nous pourrions utiliser des procédures similaires aux précédentes, mais un examen superficiel montre que seul le contenu de la requête SQL change. Il est donc très simple de créer une procédure do_execute_sql qui utilise cette
requête comme paramètres, et que nous utiliserons pour les autres traitements:
procedure do_execute_sql(p_sql: String); begin
with Form1, SqlQuery1, Sql do
begin Close; Clear;
Add(p_sql); Try
SqlConnection1.Open; ExecSql;
except
on e: Exception do
display(' *** pb_create '+ e.Message);
end; // try end; // with SqlQuery1
end; // do_execute_sql |
Nous alors créer une table des villes, comportant un numéro de ville et un nom
de ville, et nous imposerons une contrainte d'unicité au numéro. En utilisant la procédure précédente, la méthode utilisée est:
procedure TForm1.create_table_villes_Click(Sender: TObject);
begin do_execute_sql( 'CREATE TABLE villes'
+ ' ('
+ ' v_numero INTEGER NOT NULL PRIMARY KEY,'
+ ' v_nom CHAR(30)' + ' )');
end; // create_table_villes_Click |
Et pour effacer cette table, nous utiliserons:
procedure TForm1.drop_villes_Click(Sender: TObject);
begin do_execute_sql('DROP TABLE villes');
end; // drop_villes_Click |
Nous utiliserons donc la procédure do_execute_sql pour les autres instructions
de création / modification / effacement de tables.
Notre première table n'était pas dotée d'une clé unique. Nous pouvons corriger la déclaration par une instruction SQL ALTER .
ALTER TABLE formations
ADD CONSTRAINT pk_formation PRIMARY KEY (f_numero)
|
La table FORMATIONS et la table VILLES étant dotées de clés primaires, nous pouvons créer une table DATES qui contient des références vers les deux tables précédentes:
CREATE TABLE dates (
d_formation_ref INTEGER, d_ville_ref INTEGER,
d_date DATE, CONSTRAINT fk_formation
FOREIGN KEY (d_formation_ref)
REFERENCES formations (f_numero),
CONSTRAINT fk_ville
FOREIGN KEY (d_ville_ref)
REFERENCES villes (v_numero) ) |
Nous vous laissons le soin d'ajouter au projet précédent les boutons avec le code pour créer (et effacer) les deux autres tables. Le texte complet se trouve bien sûr dans oracle_dbx_create_table.zip .
Notez que: - le schéma correspondant aux trois tables que nous avons créé est le suivant:
- connaissant le schéma, nous aurions pu directement créer la table formation avec sa contrainte de clé primaire (évitant ALTER )
- notez que lorsque nous créons la table des DATES qui référence les deux
autres, celles-ci DOIVENT avoir été créées et DOIVENT avoir les champs désignés dans les contraintes FOREIGN KEY
- de façon symétrique, si nous souhaitons effacer les tables, il faut d'abord
effacer DATES, puis VILLES et FORMATIONS (si nous essayons d'effacer FORMATIONS en premier, le Serveur signale qu'il existe une référence vers cette table depuis DATES)
- nous avons fourni dans les tutoriaux Interbase des exemples de construction de tables à partir d'un schéma fourni dans un fichier .TXT
- nous aurions pu de même générer les instructions de création de table à
partir de notre outil UML qui a été utilisé pour le schéma précédent.
Voici une image de cette petite application lorsque nous avons créé les trois tables:
6 - Ajout de Données 6.1 - Ajout simple Ajoutons un enregistrement pour le stage 3, Oracle Delphi L'instruction SQL est:
INSERT INTO formations (f_numero, f_nom)
VALUES (3, 'Oracle Delphi') |
L'ajout d'enregistrement va modifier les données du Serveur, donc nous utiliserons tSqlQuery.ExecSql.
De façon détaillée: | créez une nouvelle application et nommez-la "p_oracle_dbx_insert_data" |
| placez un tSqlConnection sur la Forme - Cliquez deux fois sur SqlConnection1, renseignez "Driver Name", "Connection Name", "DataBase", "User Name" et "Pass Word".
- dans l'Inspecteur d'Objet, basculez LoginPrompt sur False, et vérifiez la connection en basculant SqlConnection1.Connected sur True, puis fermez la connection.
|
| placez un tSqlQuery sur la tForme - sélectionnez sa propriété SqlConnection et initialisez-la à SqlConnection1
|
| placez un tButton sur la Forme et créez sa méthode OnClick. Placez-y les instructions d'ajout:
procedure TForm1.insert_Click(Sender: TObject);
begin with SqlQuery1 do
begin Close;
with Sql do begin
Clear; Add('INSERT INTO formations');
Add(' (f_numero, f_nom)');
Add(' VALUES (3, ''Oracle Delphi'')'); end;
Try ExecSql;
except
on e: Exception do
display(' *** pb_insert '+ e.Message);
end; end; // with SqlQuery1
end; // insert_Click | | |
compilez, exécutez, et cliquez le bouton |
Vous pouvez télécharger les sources du projet "oracle_dbx_insert_data.zip".
6.2 - Type CHARACTER Pour spécifier les valeurs CHARACTER, Sql exige que la chaîne soit entourée de guillemets. Suivant les Serveurs, il faut utiliser un guillemet simple ou double:
VALUES (3, 'Oracle Delphi') | ou
VALUES (3, "Oracle Delphi") |
De plus si notre valeur est nichée dans une String Pascal, il faut dédoubler les guillemets simples
SqlQuery1.Sql.Add(' VALUES (3, ''Oracle Delphi'')'); |
Pour simplifier cet imbroglio de guillemets, Delphi propose la méthode QuotedStr:
IbQuery1.Sql.Add(' VALUES (3, '+ QuotedStr('Oracle')+ ')');
|
6.3 - Type NUMERIC Pour les valeurs numériques avec décimales, nous devons batailler avec les points et les virgules: La règle est donc simple: - les valeurs Delphi (Double ou autre) utilisent le point '.'
- les composants visuels (tEdit etc) et les primitives de conversion
(FloatToStr) utilisent la virgule ','
6.4 - Type DATE Un problème similaire intervient pour les dates: En supposant que nous souhaitions fournir la date du 29 Mars 2004, nous pouvons utiliser:
INSERT INTO dates (d_numero, d_date) VALUES (3, '2004/03/29') | et:
SqlQuery1.Sql.Add('INSERT INTO dates');
SqlQuery1.Sql.Add(' (d_numero, d_date');
SqlQuery1.Sql.Add(' VALUES (3, ''2004/03/29'')'); |
6.5 - Automatisation de l'Ajout Les valeurs à insérer ont été figées dans notre code. Nous pouvons généraliser cet ajout - soit en mode interactif.
- soit par une procédure amplement paramétrée
- soit par des scripts
Nous allons présenter ici l'utilisation d'une procédure paramétrée. En fait il n'y a rien de nouveau par rapport à la technique ci-dessus, sauf que - la chaîne de la requête est construite en fonction de paramètres de la procédure
- la procédure appelante envoie les paramètres requis
Voici un exemple de procédure générique d'ajout:
procedure insert_generic(p_number: Integer; p_name: String; p_days: Integer; p_cost: Double);
begin with Form1, SqlQuery1 do
begin Close;
with Sql do begin
Clear; Add('INSERT INTO formations');
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;
Try ExecSql; except
on e: Exception do
display(' *** pb_insert '+ e.Message);
end; end; // with SqlQuery1
end; // insert_generic | Et voici un exemple de procédure appelante
procedure TForm1.insert_generic_Click(Sender: TObject);
begin insert_generic(1, 'Initiation Delphi', 3, 1400.40);
insert_generic(2, 'Bases de Données Delphi', 3, 1400);
insert_generic(3, 'Oracle Delphi', 3, 1400);
insert_generic(4, 'Composants Delphi', 3, 1400);
insert_generic(5, 'UML et Patterns Delphi', 3, 1400);
insert_generic(4, 'Initiation Pascal', 4, 1900);
end; // insert_generic_Click | Notez que: - la procédure appelante pourrait aussi bien lire ses donnée d'une autre
source (un fichier FILE OF, un fichier ASCII ("comma separates values" ou autre), un autre table (Oracle, Sql Serveur ou même une autre table Interbase...)
- le paramètres p_cost est de type Double:
- la procédure appelante envoie une valeur littérale avec un point décimal
insert_generic(2, 'Bases de Données Delphi', 3, 1.400); |
- la procédure appelée utilise FloatToStr, qui attend une virgule décimale. Nous forçons donc temporairement l'utilisation du point:
DecimalSeparator:= '.';
Add(' VALUES ('+ IntToStr(p_number)+ ... + FloatToStr(p_cost)+ ')');
DecimalSeparator:= ','; |
Le fichier oracle_dbx_insert_data.zip contient aussi l'ajout utilisant un tEdit, ainsi qu'un ajout depuis un script de paramètres ASCII.
Pour vérifier que nos ajouts ont effectivement réussi, nous avons ajouté à notre application trois boutons qui ouvrent chaque table et comptent simplement le nombre de fiches.
const k_select_formations= 'SELECT * FROM formations';
procedure select(p_query: String);
var l_count: Integer; begin
with Form1 do begin
with SqlQuery1 do begin
Close;
Sql.Text:= p_query; Open;
l_count:= 0;
While not Eof do
begin Inc(l_count);
Next;
end; // while not Eot
display(' ok, '+ IntToStr(l_count)+ ' lines');
end; // with SqlQuery1
end; // with Form1 end; // select
procedure TForm1.select_Click(Sender: TObject);
begin select(k_select_formations);
end; // select_Click | Notez que pour lire les données nous avons utilisé SqlQuery1.Open (alors que
pour écrire des données, nous avons utilisé tSqlQuery.ExecSql).
Le véritable affichage du contenu de chaque ligne nous allons le réaliser maintenant, et en utilisant un tClientDataSet.
7 - Affichage des Données 7.1 - Principe de la lecture de données Nous avons vu que pour écrire des données (créer une table, ajouter des
données) SqlQuery envoyait une requête d'écriture, le Serveur effectuait l'écriture, et ne retournait quasiment rien (au mieux un message d'erreur). La situation est tout à fait différente pour la lecture. L'instruction
SELECT a pour seul but de récupérer côté client des données correspondant à une ou plusieurs tables qui existent dans la base de donnée. Ce qui change, côté Client, c'est qu'il va falloir stocker les lignes de
données correspondant à la table constituant la réponse. Certes, il arrive que la réponse ne contienne qu'un entier (SELECT COUNT ... ), mais même dans
ce cas, le résultat est considéré comme une table d'une ligne et d'une colonne. Et par conséquent les composants liés à SqlQuery doivent être prêts à effectuer ce stockage.
Voici le schéma de l'exécution d'un SELECT : - le Serveur contient une table "formations"
- le Client envoie une requête
- la requête est envoyée vers le Serveur
- le Serveur construit une NOUVELLE TABLE correspondant à la requête (même si elle sera identique à une table existante)
- les lignes de cet "answer set" sont envoyés en un ou plusieurs paquets vers le Client:
- le Client stocke les lignes et les traite:
Le type de stockage côté Client dépend de la suite de composants utilisés: - si nous travaillons directement en OCI (Oracle Call Interface : le
langage de base du Client Oracle), c'est avant d'envoyer SELECT que nous allouons un tampon mémoire pour la réponse
- si nous utilisons le BDE (Borland Database Engine: le premier moteur de base de données de Delphi, en 1996), c'est le BDE qui stockait la
réponse dans des tampons, et le composant tQuery copiait dans un autre tampon les lignes correspondant au tdbGrid ayant le plus de lignes:
- si nous utilisons dbExpress (ce qui est le cas dans cet article), le résultat est stocké par le tClientDataSet:
7.2 - Lecture dans un tClientDataSet Voici notre première application pour afficher les données: |
créez une nouvelle application et nommez-la "p_oracle_dbx_read_data" | | sélectionnez dans la page "dbExpress" de la Palette le composant
SqlConnection et posez-le sur la tForm. Cliquez deux fois sur SqlConnection1, renseignez "Driver Name" -> Oracle "DataBase" -> ORCL
"User Name" -> SCOTT "Pass Word" -> TIGER Allez dans l'Inspecteur d'Objet: - sélectionnez LoginPrompt et basculez sa valeur sur False
- vérifiez la connection en basculant Connected sur True, puis fermez la connection en basculant Connected sur False.
| |
sélectionnez dans la page "dbExpress" de la Palette le composant SqlQuery et posez-le sur la tForm. - Sélectionnez sa propriété SqlConnection et initialisez-la à SqlConnection1
- sélectionnez sa propriété SQL, cliquez sur l'ellipse ... pour ouvrir l'éditeur de chaînes de caractères et tapez-y la requête:
SELECT * FROM formations
- cliquez sur "OK" pour ferme l'éditeur
| | sélectionnez dans la page "Data Access" de la Palette le composant
DatasetProvider: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez SqlQuery1
|
| sélectionnez dans la page "Data Access" de la Palette le composant ClientDataSet:
- Posez-le sur la tForm.
- dans sa propriété ProviderName sélectionnez DatasetProvider1
|
| sélectionnez dans la page "Data Access" de la Palette le composant DataSource: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez ClientDataSet1
| | sélectionnez dans la page "Data Controls" de la Palette le composant
dbGrid: - Posez-le sur la tForm.
- dans sa propriété DataSource sélectionnez DataSource1
|
| sélectionnez sur la Forme SqlClientDataSet1, et basculez sa propriété Active à True |
| dbExpress envoie la demande d'ouverture à DataSetProvider1, qui la transmet à SqlQuery1, qui connecte la base, recherche les données et les
propage par le chemin inverse dans la dbGrid: vous voyez les donnée affichées: |
Notez l'ordre de chaînage des composants:
Cet ordre provient des multiplicités possibles: - une tSqlConnection peut être reliée à plusieurs tSqlQueries
- un tSqlQuery peut être relié à plusieurs tDatasetProviders
- un tDataSetProvider peut alimenter plusieurs tClientDatasets
- un tClientDataSet peut être relié à plusieurs tDataSource
- un tDataSource peut être relié à plusieurs composants visuels tels que la tdbGrid
Si Delphi avait proposé au développeur programmeur de relier tSqlConnection à ses tSqlQueries, il aurait fallu prévoir une LISTE de tSqlQueries associés,
alors que dans l'ordre inverse, chaque tSqlQuery ne peut avoir qu'une tSqlConnection, donc une seule ligne dans l'Inspecteur d'Objet.
En conclusion, SQL comporte deux catégories de requêtes:
- les requêtes qui écrivent des données sur le Serveur (création, envoi de données, modifications ...). Ces requêtes sont lancées en dbExpress par SqlQuery.ExecSql
- les requêtes de lecture qui vont recevoir une table réponse du Serveur, et qui sont lancées en dbExpress par SqlQuery.Open (ou son équivalent au
niveau de Inspecteur d'Objet: SqlQuery.Active:= True)
SqlQuery.ExecSql n'a aucun équivalent dans l'Inspecteur d'Objet et ne peut
être lancé qu'en exécutant le programme (alors que SqlQuery.Active peut être basculé en mode conception)
Vous pouvez télécharger le sources du projet "oracle_dbx_read_data.zip".
8 - Le mode Nomade 8.1 - Principe Nous avons vu que le tClientDataSet stockait TOUTES les lignes du résultat en mémoire.
Ce stockage choque tout le monde au départ: y aura-t-il toujours assez de place ? En fait il faut se rendre à l'évidence que l'utilisateur ne travaille jamais sur toutes les données de la base en même temps. Lorsque le préposé d'EDF vient
visiter les clients du 9ième, il n'est concerné que par les utilisateurs de cet arrondissement. Il n'a aucun intérêt à télécharger sur son appareil de relevé les 17 millions d'abonnés d'EDF de France: seuls ceux de sa tournée le
concernent. Il en est de même pour les autres traitements utilisateurs. C'est donc au développeur de formuler ses requêtes pour ne rappatrier vers le tClientDataSet que les données que l'utilisateur va réellement utiliser.
Dans ces conditions, le tClientDataset est capable de contenir toutes les données à traiter: pour l'affichage, mais aussi pour les modifications. De plus l'utilisateur peut:
- sauvegarder les données du tClientDataSet localement dans un fichier du PC client
- fermer son PC
- allumer son PC plus tard (en déplacement), recharger les données du
tClientDataSet et les utiliser (lecture, modification), puis sauvegarder les modifications:
- de retour au bureau, rallumer son PC, recharger les données modifiées et
mettre à jour les tables du Serveur
8.2 - Sauvegarde du ClientDataSet
Pour démontrer le fonctionnement nomade (BriefCase en anglais), nous allons volontairement utiliser 3 applications séparées, pour bien démontrer que le tClientDataset peut être utilisé sans aucune connection au Serveur Oracle
Tout d'abord, la première application qui charge le tClientDataset depuis le Serveur, et sauvegarde sur disque. Voici comment sauvegarder le contenu du ClientDataSet:
| créez une nouvelle application et nommez-la "p_oracle_dbx_save_cds" | |
placez un tSqlConnection sur la Forme - Cliquez deux fois sur SqlConnection1, renseignez "Driver Name" (ORACLE), "DataBase" (ORCL), "User Name" (SCOTT)et "Pass Word" (TIGER).
- dans l'Inspecteur d'Objet, basculez LoginPrompt sur False, et vérifiez la connection en basculant SqlConnection1.Connected sur True, puis fermez la connection.
|
| sélectionnez dans la page "dbExpress" de la Palette le composant SqlQuery et posez-le sur la tForm.
- Sélectionnez sa propriété SqlConnection et initialisez-la à SqlConnection1
- sélectionnez sa propriété SQL, cliquez sur l'ellipse ... pour ouvrir l'éditeur de chaînes de caractères et tapez-y la requête:
SELECT * FROM FORMATIONS - cliquez sur "OK" pour ferme l'éditeur
| |
sélectionnez dans la page "Data Access" de la Palette le composant DatasetProvider: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez SqlQuery1
|
| sélectionnez dans la page "Data Access" de la Palette le composant ClientDataSet: - Posez-le sur la tForm.
- dans sa propriété ProviderName sélectionnez DatasetProvider1
| |
sélectionnez dans la page "Data Access" de la Palette le composant DataSource: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez ClientDataSet1
|
| sélectionnez dans la page "Data Controls" de la Palette le composant dbGrid: - Posez-le sur la tForm.
- dans sa propriété DataSource sélectionnez DataSource1
| |
posez un tButton sur la Forme et faites lui ouvrir ClientDataset1: ClientDataset1.Open; | |
posez un tButton sur la Forme et faites lui sauvegarder le contenu actuel de tClientDataset: ClientDataset1.SaveToFile('RESU.XML'); |
| compilez et exécutez. Ouvrez le tClientDataSet et sauvegardez son contenu | |
le tClientDataset sauvegarde les données | | utilisez un explorateur Windows pour vérifier que le fichier est bien sur disque:
Si vous cliquez sur RESU.XML, Windows va ouvrir Internet Explorer qui va afficher, tant bien que mal, le contenu de cet fichier .XML (vue partielle):
| Notez que: - l'affichage (tDataSource et tdbGrid) n'est pas nécessaire, mais permet une vérification rapide avant sauvegarde
8.3 - Travail en mode déconnecté (Briefcase) A présent utilisons le CDS sans être connecté au Serveur:
8.4 - Mise à jour du Serveur
Pour mettre à jour le Serveur, nous utilisons simplement cds.ApplyUpdates ("effectuez les mises à jour"): |
créez une nouvelle application et nommez-la "p_oracle_dbx_update_server" | | placez un tSqlConnection sur la Forme
- Cliquez deux fois sur SqlConnection1, renseignez "Driver Name" (ORACLE), "DataBase" (ORCL), "User Name" (SCOTT)et "Pass Word" (TIGER).
- dans l'Inspecteur d'Objet, basculez LoginPrompt sur False, et vérifiez
la connection en basculant SqlConnection1.Connected sur True, puis fermez la connection.
- créez l'événement OnAfterConnect, et placez-y l'instruction
SqlConnection1.ExecuteDirect(
'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=''.,'''); | |
sélectionnez dans la page "dbExpress" de la Palette le composant SqlQuery et posez-le sur la tForm. - Sélectionnez sa propriété SqlConnection et initialisez-la à SqlConnection1
- sélectionnez sa propriété SQL, cliquez sur l'ellipse ... pour ouvrir l'éditeur de chaînes de caractères et tapez-y la requête:
SELECT * FROM FORMATIONS - cliquez sur "OK" pour ferme l'éditeur
| | sélectionnez dans la page "Data Access" de la Palette le composant DatasetProvider: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez SqlQuery1
| | sélectionnez dans la page "Data Access" de la Palette le composant
ClientDataSet: - Posez-le sur la tForm.
- dans sa propriété ProviderName sélectionnez DatasetProvider1
| |
sélectionnez dans la page "Data Access" de la Palette le composant DataSource: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez ClientDataSet1
|
| sélectionnez dans la page "Data Controls" de la Palette le composant dbGrid: - Posez-le sur la tForm.
- dans sa propriété DataSource sélectionnez DataSource1
| |
posez un tButton sur la Forme et faites lui charger ClientDataset1: ClientDataset1.LoadFromFile('RESU.XML'); |
| posez un tButton sur la Forme et faites lui mettre à jour le Serveur Oracle: ClientDataset1.ApplyUpdates(-1); |
| compilez et exécutez. Ouvrez le tClientDataSet et sauvegardez son contenu |
| le tClientDataset sauvegarde les données sur le Serveur: si vous chargez l'application qui affiche simplement le contenu de FORMATIONS, vous verrez
bien la nouvelle ligne 7 |
Notez que: - l'événement SqlConnection1.OnAfterConnect est destiné à faire accepter les décimales françaises. Si vous ne placez pas cette instruction, vous aurez
une exception "ORA-01722" (erreur de conversion d'une chaîne numérique, pour des raisons de conflit "," et "." par exemple)
- nous avons placé dans SqlQuery la requête SELECT . En effet le .XML
ne contient pas le nom de la table
- le nom de la table est "FORMATIONS" et non pas "formations". Il s'avère que dbExpress passe les noms de tables en majuscules, et donc si nous utilisons
"formations", le Serveur provoquera une exception "table pas trouvée"
9 - Modification de Données 9.1 - UPDATE L'instruction SQL de base pour modifier une donnée est UPDATE.
UPDATE formations SET f_prix= 1450
WHERE f_numero= 3 | Comme cette instruction modifie des données du Serveur, nous utiliserons un tSqlQuery et appellerons ExecSql.
procedure TForm1.update_Click(Sender: TObject);
begin with SqlQuery1 do
begin Close;
with Sql do begin
Clear; Add('UPDATE formations');
Add(' SET f_nom= '+ QuotedStr('ORACLE Delphi'));
Add(' WHERE f_numero= 3'); end;
Try ExecSql; except
on e: Exception do
display(' *** pb_insert '+ e.Message);
end; end; // with SqlQuery1
end; // update_Click | |
compilez, exécutez, et cliquez le bouton |
Vous pouvez télécharger le sources du projet "oracle_dbx_update_data.zip".
9.2 - Principe de Modification Interactive Pour modifier les données en utilisant le tClientDataset, l'utilisateur va travailler en deux étapes: - toutes les modifications (ajout, changement, effacement) sont mémorisés par
le tClientDataSet
- lorsqu'il le souhaite, l'utilisateur peut envoyer les modifications vers le Serveur Interbase
L'utilisateur travaille donc dans un premier temps uniquement avec la mémoire
du tClientDataSet. Celui-ci garde la trace intégrale de toutes les modifications: - si nous modifions un enregistrement, nous aurons 6 fois l'enregistrement en mémoire (l'original et les 5 modifications)
- les ajouts sont placés dans la mémoire
- les effacements sont mémorisés comme une nouvelle ligne avec une marque d'effacement.
9.3 - Les Modifications de tClientDataset
Le tClientDataset contient donc une suite de lignes numérotées: - les lignes chargées lors de l'ouverture de tClientDataset
- les lignes ajoutées
- les versions modifiées de lignes précédentes
- les lignes effacées
Le dbGrid ne présente quant à lui que la dernière version de chaque ligne.
Pour visualiser les lignes originales et leurs versions successives, nous
allons simplement sauvegarder le tClientDataset dans un fichier .XML et réafficher ce fichier .XML. Ce type d'analyse a été présenté dans l'article
Affichage ClientDataset XML. Nous nous contenterons ici d'appeler les classes d'analyse et d'affichage. Par conséquent:
| créez une nouvelle application et appelez-la "p_oracle_dbx_modify_cds.dpr" | |
placez un tSqlConnection sur la Forme - Cliquez deux fois sur SqlConnection1, renseignez "Driver Name" (ORACLE), "DataBase" (ORCL), "User Name" (SCOTT)et "Pass Word" (TIGER).
- dans l'Inspecteur d'Objet, basculez LoginPrompt sur False, et vérifiez la connection en basculant SqlConnection1.Connected sur True, puis fermez la connection.
- créez l'événement OnAfterConnect, et placez-y l'instruction
SqlConnection1.ExecuteDirect( 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=''.,'''); |
| sélectionnez dans la page "dbExpress" de la Palette le composant SqlQuery et posez-le sur la tForm.
- Sélectionnez sa propriété SqlConnection et initialisez-la à SqlConnection1
- sélectionnez sa propriété SQL, cliquez sur l'ellipse ... pour ouvrir l'éditeur de chaînes de caractères et tapez-y la requête:
SELECT * FROM FORMATIONS - cliquez sur "OK" pour ferme l'éditeur
| |
sélectionnez dans la page "Data Access" de la Palette le composant DatasetProvider: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez SqlQuery1
|
| sélectionnez dans la page "Data Access" de la Palette le composant ClientDataSet: - Posez-le sur la tForm.
- dans sa propriété ProviderName sélectionnez DatasetProvider1
| |
sélectionnez dans la page "Data Access" de la Palette le composant DataSource: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez ClientDataSet1
|
| sélectionnez dans la page "Data Controls" de la Palette le composant dbGrid: - Posez-le sur la tForm.
- dans sa propriété DataSource sélectionnez DataSource1
| |
posez un tButton sur la Forme et faites lui ouvrir ClientDataset1: ClientDataset1.Open; | |
ajoutez un tButton pour afficher le contenu actuel du ClientDataset1 (optionnel): - ajoutez u_c_cds_analyze_xml et u_cds_table à la liste des USES
- posez un tButton sur la Forme et tapez le code d'affichage:
procedure TForm1.display_xml_Click(Sender: TObject);
var l_c_table: c_table; begin
// -- save the CDS with some temporary name
ClientDataset1.SaveToFile(k_root_path+ 'temp.xml');
// -- reload the CDS and display it
with c_cds_analyze_xml.create_cds_analyze_xml('xml',
k_root_path+ 'temp.xml') do begin
l_c_table:= c_table.create_table('table');
analyze_xml(l_c_table); display_line;
l_c_table.display_formatted_line_list; l_c_table.Free;
Free; end; // with c_analyze_xml
end; // display_xml_Click | | |
posez un tButton sur la Forme et faites lui mettre à jour le Serveur: ClientDataset1.ApplyUpdates(-1); |
| posez un tButton sur la Forme et faites lui mettre à jour le Serveur: ClientDataset1.Close; |
| compilez et exécutez |
A présent voici un exemple de manipulation:
9.4 - Réconciliation de Données
Si deux agences de voyages essayent simultanément de réserver sur le même vol plus de place qu'il n'en reste, la grogne à l'enregistrement est garantie. Il faut donc trouver un moyen d'arbitrer entre les requêtes incompatibles.
Nous n'allons pas rentrer ici dans le détail des mode de transaction et des verrouillages. Mais voici comment fonctionne une façon de traiter le problème:
- Oracle (comme les autres moteurs: Interbase, Sql Serveur, DB2, MySql etc) fonctionne en mode "optimiste": plusieurs utilisateurs peuvent charger
une ligne, et la modifier. C'est le dernier qui a parlé qui a raison
- nous pouvons demander à dbExpress de vérifier avant de mette à jour que les valeur actuellement sur le Serveur sont bien les mêmes que celles que nous
avons chargées 10 minutes plus tôt (en français clair: un autre utilisateur a-t-il effectué des modifications depuis notre chargement ?). Cela se fait
simplement en ajoutant à UPDATE une clause WHERE qui vérifie que la valeur est celle que nous avons chargée avant nos modifications). Pour faire simple, cette clause pourrait être:
UPDATE formations SET f_nom= 'ORACLE DELPHI
WHERE (f_numero= 3) AND (f_nom= 'ORACLE Delphi') |
- si UPDATE échoue (parce que WHERE ne trouve plus nos valeurs initiale), dbExpress provoque une exception nous indiquant qu'un autre utilisateur a modifié les données
- notre application a alors la main. Nous pouvons décider de forcer un UPDATE (écrasant la valeur des autres utilisateurs), ignorer l'erreur, envoyer un message à l'utilisateur en lui demandant de recommencer en
partant des nouvelles valeurs actuellement sur le Serveur etc
- pour faciliter la gestion de ces exceptions, dbExpress nous propose un dialogue par défaut affichant à le conflit de résolution et permettant à
l'utilisateur de choisir le type de traitement à effectuer (ignorer, écraser etc)
Voyons plus en détail comment gérer les erreur de réconciliation. Il faut tout
d'abord créer l'événement OnReconcileError du tClientDataset. Les paramètres sont les suivants:
PROCEDURE ReconcileError( p_c_data_set: TCustomClientDataSet;
p_c_error: EReconcileError; p_update_kind: TUpdateKind;
VAR pv_action: TReconcileAction); | et: - p_c_data_set: c'est le tClientDataSet qui contient les erreurs
- p_c_error: une exception contenant dans p_c_error.Message le texte de l'exception
- p_update_kind indique si l'erreur provenant d'un ajout (ukInsert), d'une
modification (ukModify) ou d'un effacement (ukDelete)
- pv_action: indique ce qu'il faut faire de cette erreur (annuler, forcer la valeur etc)
Et Borland suggère même d'utiliser un dialogue tout préparer pour proposer à l'utilisateur de décider ce qu'il faut faire en lui présentant directement le problème et le le laissant choisir le traitement à effectuer. Ce dialogue
appelé RECERROR.PAS se trouve dans: C:\PROGRAM FILES\BORLAND\DELPHI6\OBJREPOS et a l'allure suivante: et: - il affiche l'erreur
- présente les données ayant causé la faute
- laisse l'utilisateur décider ce qu'il souhaite faire
Pour utiliser ce dialogue: Finalement pour comprendre les commandes que Delphi génère pour nous lors de
l'appel de tClientDataset.ApplyUpdates, nous allons employer un SqlMonitor qui affiche les API Interbase envoyées vers le Serveur Interbase. Pour cela il suffit de
- relier le tSqlMonitor à tSqlConnection
- basculer tSqlMonitor sur True
- créer l'événement tSqlMonitor.OnLogTrace et visualiser tSqlMonitor.TraceList
Créons à présent l'application qui permet les modifications: | créez une nouvelle application et appelez-la "p_oracle_dbx_reconcile.dpr" |
| placez un tSqlConnection sur la Forme - Cliquez deux fois sur SqlConnection1, renseignez "Driver Name"
(ORACLE), "DataBase" (ORCL), "User Name" (SCOTT)et "Pass Word" (TIGER).
- dans l'Inspecteur d'Objet, basculez LoginPrompt sur False, et vérifiez la connection en basculant SqlConnection1.Connected sur True, puis
fermez la connection.
- créez l'événement OnAfterConnect, et placez-y l'instruction
SqlConnection1.ExecuteDirect(
'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=''.,'''); | |
sélectionnez dans la page "dbExpress" de la Palette le composant SqlQuery et posez-le sur la tForm. - Sélectionnez sa propriété SqlConnection et initialisez-la à SqlConnection1
- sélectionnez sa propriété SQL, cliquez sur l'ellipse ... pour ouvrir l'éditeur de chaînes de caractères et tapez-y la requête:
SELECT * FROM FORMATIONS - cliquez sur "OK" pour ferme l'éditeur
| | sélectionnez dans la page "Data Access" de la Palette le composant DatasetProvider: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez SqlQuery1
- dans sa propriété UpdateMode, sélectionnez UpWhereAll (ne mettre à jour que si la ligne est exactement celle que nous avons initialement chargée)
|
| sélectionnez dans la page "Data Access" de la Palette le composant ClientDataSet: - Posez-le sur la tForm.
- dans sa propriété ProviderName sélectionnez DatasetProvider1
| |
sélectionnez dans la page "Data Access" de la Palette le composant DataSource: - Posez-le sur la tForm.
- dans sa propriété DataSet sélectionnez ClientDataSet1
|
| sélectionnez dans la page "Data Controls" de la Palette le composant dbGrid: - Posez-le sur la tForm.
- dans sa propriété DataSource sélectionnez DataSource1
| |
posez un tButton sur la Forme et faites lui ouvrir ClientDataset1: ClientDataset1.Open; | |
posez un tButton sur la Forme et faites lui mettre à jour le Serveur: ClientDataset1.ApplyUpdates(-1); |
| ajoutez à la liste des USES la forme de réconciliation: USES .... recerror, ... | |
créez le gestionnaire d'erreur: - sélectionnez ClientDataset1
- créez son événement OnReconcileError
- appelez la Forme de réconciliation et retournez le code à Delphi:
procedure TForm1.ClientDataSet1ReconcileError(
DataSet: TCustomClientDataSet; E: EReconcileError;
UpdateKind: TUpdateKind; var Action: TReconcileAction);
begin display('reconcile '+ e.Message);
action:= HandleReconcileError(DataSet, UpdateKind, e);
end; // ClientDataSet1ReconcileError | |
| ajoutez la trace Sql: - sélectionnez dans la page "dbExpress" de la Palette le composant SqlMonitor:
- Posez-le sur la tForm.
- sélectionnez SqlConnection et mettez-y SqlConnection1
- sélectionnez Active et basculez le sur True
- créez son événement OnLogTrace et affichez les textes:
var g_trace_count: Integer= 0;
procedure TForm1.SQLMonitor1LogTrace(Sender: TObject;
CBInfo: pSQLTRACEDesc);
var l_length: Integer;
l_text: String; begin
with CBinfo^ do begin
l_length:= uTotalMsgLen;
if l_length> 0
then begin
SetLength(l_text, l_length);
Move( psztrace, l_text[1], l_length);
display(l_text);
end; end;
with SQLMonitor1, TraceList do
while g_trace_count< Count do
begin
display(Strings[g_trace_count]);
Inc(g_trace_count); end;
end; // SQLMonitor1LogTrace | | |
compilez et exécutez |
Et pour vérifier le fonctionnement: | lancez l'exécution, cliquez sur "open_cds_" |
| nous chargeons la table, et, entre autre "3, ORACLE DELPHI" | |
pour simuler un autre utilisateur, allez dans un explorateur Windows et lancez une seconde instance de p_oracle_dbx_reconcile_cds.exe. - cliquez sur "open_cds_"
- modifiez "3, ORACLE DELPHI" en "3, ORACLE et delphi"
- descendez verticalement pour poster
- mettez à jour le Serveur en cliquant "ApplyUpdates_"
- fermez cette application
| |
retournez dans la première instance - Modifiez "3, ORACLE DELPHI" en "bdd oracle delphi"
- descendez verticalement pour poster
- cliquez "ApplyUpdates_"
|
| Delphi affiche une exception: |
| cliquez "OK" pour fermer le dialogue, puis "Run" dans le menu Delphi | | Delphi affiche le dialogue de réconciliation
| | choisissez une des options, par exemple "correct" et cliquez "ok" |
| Delphi réaffiche la dbGrid, et nous laisse modifier / mettre à jour etc |
10 - Et Maintenant ... Dans ce premier article, nous n'avons pas présenté: - la gestion de Serveur (sauvegarde / restauration, les différents modèles Oracle ...)
- le détail des types de données
- le détail de traitement de tClientDataset
- procédures stockées, les triggers, les séqueces
- traitement détaillé de la réconciliation
- la gestion des transactions, les modes de transisolation
- l'édition d'états
- la gestion des erreurs
De plus: - nous proposons des stages de formations pour les
personnes qui souhaiteraient approfondir ce qui a été présenté ici. Le but est de rendre les stagiaires rapidement opérationnels et de répondre aux questions qu'ils auraient pu se poser au cours de premiers contacts avec le
développement d'applications Oracle.
- et nous avons aussi compilé une liste de liens Oracle destinée tout particulièrement aux dévelopeurs.
11 - Télécharger le code source Vous pouvez télécharger: Ce .ZIP qui comprend:
- 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, pour les projets en Delphi 6, 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.
La notation utilisée est la notation alsacienne qui consiste à préfixer les identificateurs par la zone de compilation: K_onstant, T_ype, G_lobal,
L_ocal, P_arametre, F_unction, C_lasse. Elle est présentée plus en détail dans l'article La
Notation Alsacienne
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" :
- 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.
12 - 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. |