|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | |
|
Membre du Club
![]() Inscription : juin 2002 Messages : 206 ![]() |
Bonjour,
J'écris un petite application avec: -des caches de mise a jour(TClientDataSet et TDataSetProvider) - J'ai deux tables liées entre elle via un cle (ID) dans un SGBD FireBird -Chaque cle primaire sur chaque table sont auto incrémenté via un générateur -Dans C++Builder j'ai établie une liaison Maitre/detail via les 2 caches(1 sur chaque table) -Les données sont affichées via deux Dbgrid Lorsque je travaille en local , je me coupe du réseau je voudrais savoir comment vous gérez les index avant de faire les mise a jour sur le SGBD ? Lorsque je travaille en local et que j'essaie d'ajouter des valeurs, du fait de ma relation maitre/détail j'ai un exception déclenchée : Citation:
- Est ce que vous faite de requête sql pour savoir le nb d'enreg cote serveur? - Est ce que vous calculez l'ID max et est ce vous l'utilisez par programmation coté client via BCB6 ? Je vous remercie par avance
__________________
Outils utilisés : FireBird 2.1 - IbExert Free - C++ Builder 6 Pro Update 4- Windows Xp pro Sp3 |
|
|
|
00
|
|
|
#2 | ||
|
Membre éprouvé
![]() Analyste-développeur Inscription : mai 2002 Messages : 994 ![]() |
Bonjour,
Cela ne fait pas longtemps que j'ai commencer à utiliser le TClientDataset surtout que depuis que j'ai commencer avec FB et je n'ai pas de problème en travaillant en mode déconnecté. Personnellement, je ne fais pas de requête coté serveur pour obtenir le max d'enregistrements pour l'insertion. Il faut garder le moins longtemps possible des transactions ouvertes en sollicitant de moins en moins le serveur quand cela est possible. En récupérant le max depuis le serveur c'est à dire que le générateur nous renvois sa valeur+1 et si on a plusieurs clients en même temps qui demande ce max et que certains d'eux annule la requête, alors on se retrouvera avec des trous d'ID. En mode déconnecter, le max de l'identifiant de chaque table je le récupère en local et l'incrémente à chaque insert d'un enregistrement et ce, soit dans l'evenement OnBeforeInsert du TclientDataSet ou lorsque je fais : Code :
Les identifiants changeront par la suite via un générateur que vous aurez créer au niveau de la BDD lorsque vous démarrerez la transaction après le commit et un refresh pour récupérerer les enregistrements insérées avec leurs nouveaux identifiants. Dans une même transaction, j'envoie en premier lieu l'enregistrement maitre et je récupérer en retour son identifiant pour que je puisse l'affecter à la clé étrangère des enregistrements de la table secondaire qui seront envoyés toujours dans la même transaction. C'est la méthode que j'utilise actuellement et j'ai pas de problème avec. Je ne sais pas si il y a mieux que ça.
__________________
Il n' y a de Pouvoir que le Savoir djasoft ! est un logiciel de gestion de stocks et commercial totalement gratuit pour auto-entrepreneurs, PME, TPE, Artisans et Indépendants Annuaire de référencement gratuit |
||
|
|
00
|
|
|
#3 |
|
Membre du Club
![]() Inscription : juin 2002 Messages : 206 ![]() |
merci je vais voir de ce cote la....
cela marche chez moi mais sur l'évènement AfterInsert Comment modifiier le générateur pour les initialiser a 0 par une procédure stockée ? merci
__________________
Outils utilisés : FireBird 2.1 - IbExert Free - C++ Builder 6 Pro Update 4- Windows Xp pro Sp3 |
|
|
00
|
|
|
#4 | |||||
|
Membre éprouvé
![]() Analyste-développeur Inscription : mai 2002 Messages : 994 ![]() |
Bonjour,
Citation:
Pour modifier la valeur d'un générateur , il semblerais que les commandes DDL (create,alter,...) ne sont pas accepter dans une PS il faut utiliser à la place un EXECUTE STATEMENT dans une PS : Code :
Code :
__________________
Il n' y a de Pouvoir que le Savoir djasoft ! est un logiciel de gestion de stocks et commercial totalement gratuit pour auto-entrepreneurs, PME, TPE, Artisans et Indépendants Annuaire de référencement gratuit |
|||||
|
|
00
|
|
|
#5 | ||||||
|
Membre du Club
![]() Inscription : juin 2002 Messages : 206 ![]() |
Bonjour
merci vraiment des première réponse J'ai plusieurs petites questions: Ou trouver des tutoriel pour le langage spécifique (DDL,Procedure Stockée,etc) à Firebird ? Je connais déjà SQL Pour le MAX (coté client) ,voici comment je procède : le contrôle qui me sert a valider est un DBNavigator As tu mieux a me proposer ? 1:Fonction Max : Code C++ :
2: Sur le constructeur de mon datamodule Code c++ :
3: Pour générer un ID+1 sur AfterInsert Code c++ :
merci encore
__________________
Outils utilisés : FireBird 2.1 - IbExert Free - C++ Builder 6 Pro Update 4- Windows Xp pro Sp3 |
||||||
|
|
00
|
|
|
#6 | ||
|
Membre éprouvé
![]() Analyste-développeur Inscription : mai 2002 Messages : 994 ![]() |
Pour les tutoriels
Il y a pas mieux que la base de données Employee.fdb pour commencer. Elle se trouve dans le dossiers examples\empbuild de Firebird. Elle contient de bons exemples simplifiés sur les PS et les Triggers. Voir Introduction au langage SQL avec le SGBD Firebird Voir les manuels d'interbase 6.0 & Firebird sur le site officiel de Firebird il y a peu de différences entre Interbase et Firebird puisque le 2eme est issu du 1er. La version française de la doc d'Interbase 6 existe je ne souviens plus à quel endroit faire une petite recherche sur google Des cours et tutoriaux sur Interbase/Firebird sur developpez.com La faq ça aide beaucoup Ici Une très bonne faq en anglais avec des How's to Ici Voir les tutoriels de Colibri sur Interbase/Firebird enrichis d'exemples avec Delphi Ici Des outils gratuits pour gérer les Bases de données Flamerobin outil multi-plateformes IBExpert Edition personnelle Pour le calcul du Max de l'identifiant -soit créer un index dans le composant TclientDataset (clic droit) dans la propriété IndexDefs, nommée l'index et affecter à la propriété Field le champ autoIncrement et dans IndexName sélectionner le nom de l'index créer. Ensuite faire Table.Last et récupérer la dernier valeur du champ qui sera la valeur maximale -soit dans la propriété aggregates et dans la petite fenêtre qui apparait vous donnez un nom dans AggregateName par ex MaxId et dans Expression utiliser la fonction MAX(champ_identifiant) et récupérer le max de l'id ainsi : Code :
En espérant vous avoir donner entière satisfaction.
__________________
Il n' y a de Pouvoir que le Savoir djasoft ! est un logiciel de gestion de stocks et commercial totalement gratuit pour auto-entrepreneurs, PME, TPE, Artisans et Indépendants Annuaire de référencement gratuit |
||
|
|
00
|
|
|
#7 |
|
Expert Confirmé
![]() ![]() ![]() Philippe MakowskiConsultant spécialité Firebird Inscription : mai 2002 Messages : 2 258 ![]() |
__________________
Philippe Makowski IBPhoenix - Firebird Membre de l'April |
|
00
|
|
|
#8 | |||
|
Membre du Club
![]() Inscription : juin 2002 Messages : 206 ![]() |
Encore un grand merci a toi Freud pour tes infos
j'ai adopte ta seconde méthode qui est très efficace et surtout qui permet de gérer moins de code le code change légèrement en BCB6pro Code c++ :
![]() ![]() merci pour le liens! Citation:
-Table Personne clé primaire ID_PERS....etc -Table Téléphone clé primaire ID_TEL , clé étrangère #ID_PERS...etc -sur chaque table il y a des générateurs auto incrémenté pour ID_PERS et ID_TEL avec comme règle Personne.ID_PERS=Téléphone.ID_PERS. De plus J'ai deux grilles (DbGrid) dans C++Builder qui sont liées via un relation Maitre/Détail -Les données sont stockée dans des caches Pour chaque insert je dois fournir impérativement un ID_PERS et un ID_TEL afin de ne pas lever un exception d'où mon calcul du max pour preremplir un champ Comment faites cela dans une apllication Delphi ou C++Builder pour faire ceci ?En vous remerciant par avance de votre précieuse dans le passé ainsi que de votre réponse
__________________
Outils utilisés : FireBird 2.1 - IbExert Free - C++ Builder 6 Pro Update 4- Windows Xp pro Sp3 |
|||
|
|
00
|
|
|
#9 | |
|
Expert Confirmé
![]() ![]() ![]() Philippe MakowskiConsultant spécialité Firebird Inscription : mai 2002 Messages : 2 258 ![]() |
Citation:
ce n'est pas normal, c'est le serveur qui à l'aide du trigger et de la sequence qui doit remplir ces champs, pas ton appli ton appli est mal conçue à ce niveau
__________________
Philippe Makowski IBPhoenix - Firebird Membre de l'April |
|
|
00
|
|
|
#10 |
|
Membre du Club
![]() Inscription : juin 2002 Messages : 206 ![]() |
Merci de votre réponse
auriez vous un petit exemple sur une table ?
__________________
Outils utilisés : FireBird 2.1 - IbExert Free - C++ Builder 6 Pro Update 4- Windows Xp pro Sp3 |
|
|
00
|
|
|
#11 |
![]() ![]() Claude RenouleaudDéveloppeur informatique Inscription : février 2006 Messages : 4 860 ![]() |
Comme dit Philippe, laisse le serveur faire ce qui est son travail.
L'appel à un générateur se fait hors transaction ce qui assure l'unicité de la valeur, même (et surtout) lors d'accès concurrentiels. Puisque tu es sous FB2.1, utilise la clause RETURNING lorsque tu effectues un INSERT dans un table. Voir les notes de versions: Claudius
__________________
A la question technique que par MP/MV tu formuleras, la réponse aux oubliettes finira. |
|
|
00
|
|
|
#12 | |
|
Membre éprouvé
![]() Analyste-développeur Inscription : mai 2002 Messages : 994 ![]() |
Citation:
Mais là, non seulement déconnecter du serveur mais du réseau aussi. Donc, son souci c'est de pouvoir maintenir une relation maitre/détail entre deux tables dans lesquelles il fera des Insert, des Edit et des Delete. N'étant pas connecter au réseau, il faudra bien qu'il puisse maintenir cette relation par un système de clés d'où la fonction d'incrémentation temporaire (puisque comme il le précise aussi Chaque cle primaire sur chaque table sont auto incrémenté via un générateur) des clés en local avant que les données ne puisse être envoyer au serveur ou d'être sauvegarder sur disque en différant leurs envois. A moins que le TclientDataSet offre un système d'identifiants interne propre à lui que je ne connais pas ...........(????)
__________________
Il n' y a de Pouvoir que le Savoir djasoft ! est un logiciel de gestion de stocks et commercial totalement gratuit pour auto-entrepreneurs, PME, TPE, Artisans et Indépendants Annuaire de référencement gratuit |
|
|
|
00
|
|
|
#13 | |
![]() ![]() Claude RenouleaudDéveloppeur informatique Inscription : février 2006 Messages : 4 860 ![]() |
Citation:
Mais il faudra bien à un moment ou à un autre que o_live applique ces INSERTs. D'un autre côté je n'utilise pas le TClientDataSet beaucoup trop lourd (et lent) à mon goût.
__________________
A la question technique que par MP/MV tu formuleras, la réponse aux oubliettes finira. |
|
|
|
00
|
|
|
#14 | |||||||||
|
Membre du Club
![]() Inscription : juin 2002 Messages : 206 ![]() |
Bonsoir a tous
le modèle physique de données est comme ceci (on fait avec le moyens du bord .... Table Personne ID_PERS (cle primaire) PRENOM NOM Table Telephonne ID_PERS# ID_TEL (cle primaire) NUMERO TYPE Ces 2 table sont liées avec cette regle de gestion Personne.ID_PERS=Telephonne.ID_PERS Voici cote client en detail (C++Builder ) mon module de donnée Code C++ :
Partie MAITRE Table Personne Code :
Partie Detail Table Telephonne Code C++ :
Âpres avoir charger les infos et m'être déconnecté du réseau Lorsque je clique sur une personne j'ai tous ses téléphones les deux grilles sont synchronisées Les données de chaque table sont stockées dans chacun des caches CDSPers et CDSTel Si je veux insérer un nouvel enregistrement coté client, en mémoire cache comme ceci Code c++ :
Question 1:Comment est ce que je peux dire au serveur FB de me donner un nouvel ID ? -Si je ne donne pas de ID_PERS correct j'ai une exception qui se léve Citation:
-Le nouveau enregistrement sera validé en mémoire cache après avoir fait appel de la méthode CDSPers->Post() -Les Données ne seront Appliquées définitivement inscrites dans le SGBD qu'après avoir faits appel de la méthode CDSPers->ApplyUpdates() Question 2 : j'ai vu sur le composant IBQuery une propriété GeneratorField comment utilise ton cette propriété ? Qui peut m'expliquer ceci ? Je vous remercie de m'avoir lu est espère avoir été plus clair Remarque : Lorsque je fais des requêtes de type Insert je me sert du composant StoredProc pour les procédure stockée .Je ne mentionne pas ID_PERS puisque le générateur me donne un nouvel ID_PERS a chaque insertion
__________________
Outils utilisés : FireBird 2.1 - IbExert Free - C++ Builder 6 Pro Update 4- Windows Xp pro Sp3 |
|||||||||
|
|
00
|
|
|
#15 | |
|
Expert Confirmé
![]() ![]() ![]() Philippe MakowskiConsultant spécialité Firebird Inscription : mai 2002 Messages : 2 258 ![]() |
Citation:
sinon il suffit d'interroger la sequence (ou générateur c'est la même chose)
__________________
Philippe Makowski IBPhoenix - Firebird Membre de l'April |
|
|
00
|
|
|
#16 |
|
Membre Expert
![]() Frédéric Inscription : octobre 2002 Messages : 1 726 ![]() |
Bonjour,
Je n'utilise pas de TClientDataset ni de mode déconnecté. Mais il faut comprendre une chose, c'est lorsque vous vous reconnectez pour insérer de nouvelles personnes il vous faut utiliser les générateurs de firebird. C'est le moyen le plus sur de ne pas avoir de message d'erreur sur le clé primaire. S'il n'y a qu'une seule personne qui utilise la base de données, utiliser max() fonctionnera mais c'est une très mauvaise pratique. Et elle vous empêchera d'utiliser votre application en multi-poste et dans ce cas pourquoi utiliser une serveur ? autant utiliser firebird embedded.. Donc nous n'avons pas le choix, il faut utiliser les générateurs. Ceux-ci n'étant accessibles que lorsque l'on est connecté il vous faudra gérer les clés en local lorsque vous n'êtes pas connectés. Donc en mode déconnecté, lorsque vous voulez insérer vous générez vos identifiants (avec max si vous le voulez). Lorsque vous vous connectez vous allez synchroniser les données avec "ApplyUpdates". L'évènement "BeforeUpdateRecord" est lancé avant chaque mise à jour, c'est dans ce gestionnaire d'évènement qui vous faudra identifier les insertions (UpdateKind=ukInsert) et donc demander un identifiant au serveur (select gen_id(gen_personne, 1) from rdb$database;) et remplacer l'identifiant de l'insert par celui du serveur. Enfin mettre a jour les identifiants de la table esclave (téléphones). |
|
|
00
|
|
|
#17 | ||||
|
Membre éprouvé
![]() Analyste-développeur Inscription : mai 2002 Messages : 994 ![]() |
Barbibulle l'a clairement expliquer mais comme il dit qu'il est coupé du réseau
donc on ne peut donc que supposer qu'il n'a pas accés au serveur comme il le veut. Citation:
Vous obtiendrais vos ID's définitif (mise à jour des identifiant) que lorsque vous vous reconnecter au serveur pour l'envoi des données En ayant au préalable créer un Trigger Before Insert pour générer vos ID's comme ceci : Code :
si oui : alors a l'insertion se fera directement vers le serveur il sera donc inutile de générer des ID's maitre/detail localement du fait que le serveur le fera lui-même à l'aide du trigger. Et comme l'a dit Cl@udius, utilisez la clause RETURNING pour récupérer l'ID maitre afin de renseigner le champ ID_PERS de la table Telephonne lorsque vous posterez les données de cette table. si non : alors vous pouvez maintenir la méthode d'incrémentation des ID's en local lorsque vous procéder à des insertions et ce, pour le maintien des enregistrements du maitre avec son détail en attendant que vous ayez accés au serveur et mettre à jour vos identifiants. Citation:
D'autant plus que l'appel au Max ne se fera qu'une fois et stocké par exemple dans une variable public.
__________________
Il n' y a de Pouvoir que le Savoir djasoft ! est un logiciel de gestion de stocks et commercial totalement gratuit pour auto-entrepreneurs, PME, TPE, Artisans et Indépendants Annuaire de référencement gratuit |
||||
|
|
00
|
|
|
#18 |
|
Membre du Club
![]() Inscription : juin 2002 Messages : 206 ![]() |
Merci de vos conseil précieux a tous
![]() ![]() Comme dit Barbibulle,je crois qu'il est judicieux d'interroger les générateur au dernier moment pour être sur d'avoir les bonnes valeur des ID dans le Update surtout dans un mode client/Serveur. Le composant IBQuery a une propriété GeneratorField qui liste les générateurs pressent dans la base est ce que cela ne pourrait pas être une solution ? comment l'utiliser ? Feud :dans ma dernière version j'avais réglé via Aggregate le Pb dans mon ancienne version mais dans la nouvelle non Encore merci a tous
__________________
Outils utilisés : FireBird 2.1 - IbExert Free - C++ Builder 6 Pro Update 4- Windows Xp pro Sp3 |
|
|
00
|
|
|
#19 | |
|
Membre Expert
![]() Frédéric Inscription : octobre 2002 Messages : 1 726 ![]() |
Citation:
|
|
|
|
00
|
|
|
#20 | |||||
|
Membre éprouvé
![]() Analyste-développeur Inscription : mai 2002 Messages : 994 ![]() |
Bonjour,
Citation:
Citation:
Cela veut dire que, d'une manière ou d'une autre, on aura toujours affaire au générateur au final qui se chargera d'attribuer une clé unique à ces enregistrements. Citation:
Pour les générateur dans GeneratorField. Cela vous a été suggérer de gérer vos générateurs au niveau du serveur à l'aide de triggers. -créer le trigger BeforeInsert avec son générateur -créer la PS avec Code SQL :
-démarrage de la transaction -parcourir le cds maitre avec test if cdsPersonne.UpdateStatus=usInserted then exécutez votre PS avec la query dans laquelle vous récupérez l'ID en fin d'exécution -parcours le cds detail avec un test if dsTelephone.UpdateStatus=usInserted then exécutez votre PS en renseignant PERS de la table Telephone avec l'ID récupérer précédemment -Commit de la transaction -cdsPerson.MergeLog -cdsTelephone.MergeLog (effacement du journal des modifications pour eviter de renvoyer même données.) -rafraichissement par un select. Ne pas invoquer d'applyupdate ni de coder dans le TDataSetProvider. Il n'y aura aucun problème d'accès concurrentiel et......, transactionnel multi-poste. Bien entendu, le CDS est fourni pour être déployer dans des applications multi-tiers mais dans votre cas il peut-être utiliser dans un environnement 2-tiers avec cette façon de faire décrite ci-dessus.Car, dans la réalité, son utilisation est tout autre et est encore plus sophistiquer.
__________________
Il n' y a de Pouvoir que le Savoir djasoft ! est un logiciel de gestion de stocks et commercial totalement gratuit pour auto-entrepreneurs, PME, TPE, Artisans et Indépendants Annuaire de référencement gratuit |
|||||
|
|
00
|
Copyright © 2000-2013 - www.developpez.com