Enregistrement dupliqué

Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009 - 22 avril 2009 à 09:30
Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009 - 6 mai 2009 à 08:57
Bonjour,

J'ai un problème incompréhensible, j'utilise vfp6, une base de donnée Foxpro et un formulaire tout à fait classique pour naviguer dans une table. J'ai des boutons pour modifier la fiche en cours, ajouter une fiche, etc. et bien sur les boutons OK et Annuler.
Mon souci survient lorsqu'on enregistre une fiche lors d'une modification, en cliquant sur le bouton OK je crée un doublon dans ma table. L'inconvénient c'est que cela se produit de façon aléatoire et impossible bien sur de trouver la raison.
Si quelqu'un a une idée car je sèche la-dessus.
Merci.

12 réponses

michelatoutfox Messages postés 828 Date d'inscription mardi 5 octobre 2004 Statut Membre Dernière intervention 7 mai 2013 1
22 avril 2009 à 12:44
Bonjour Etienne,

on n'est pas dans ton code, on n'a pas de boule de cristal  alors, donne-nous plus de renseignements si tu veux qu'on t'aide!

quelle est la structure de cette table? y a-t-il une clé primaire, ou un index candidat, et si oui, sur quel champ ou expression de champ?
comment détermines-tu que tu as un doublon?
quel est le code qui est exécuté quand tu cliques sur ce bouton OK? as-tu regardé ce qui se passe en mettant un point d'arret au déboguage sur ce code?
0
Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009
22 avril 2009 à 14:32
Bonjour Michel,

Je te remercie de consacrer du temps aux problèmes des autres, j'ai remarqué que tu interviens souvent, c'est vraiment sympa.

J'utilise donc une table sans clé primaire, par contre elle est indexée sur l'identifiant de la fiche (dans un cdx). Dans le bouton OK, je détecte si je suis en modification, si c'est le cas je fais un "gather from memvar"; si je suis en ajout je fais un "insert into matable from memvar".
Il n'y a rien de plus mis à part la réinitialisation de variables.
Je constate un doublon, car en fait l'identifiant de la fiche et les autres champs de la fiche ont été recopiés sur un enregistrement précédent, comme si le pointeur de fichier a été déplacé et que le "gather from memvar" se fait ensuite.
0
michelatoutfox Messages postés 828 Date d'inscription mardi 5 octobre 2004 Statut Membre Dernière intervention 7 mai 2013 1
22 avril 2009 à 16:13
je t'ai demandé:
1) le code exécuté par ce bouton OK,
2) la structure de cette table

on continue quand tu auras fourni ces éléments.
0
Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009
22 avril 2009 à 18:06
Voici les éléments demandés :

pour la table :
Champ Nom de champ Type Largeur Déc Index
1 IDENREG Caractère 10
2 CIVENREG Caractère 4
3 NOMENREGIS Caractère 20
4 PRENENREG Caractère 20
5 IDRECOMM Caractère 30
6 IDCAHIER Caractère 10
7 DATENREG Date 8 Crois.
8 HEURENREG Caractère 8
9 IDDUCAHIER Caractère 10
10 IDLIVREUR Caractère 10
11 CIVLIVR Caractère 4
12 LIVREUR Caractère 20
13 PRENLIVR Caractère 20
14 IDPORTE Caractère 10
15 CIVPORT Caractère 4
16 NOMPORTE Caractère 20 Crois.
17 PRENPORT Caractère 20
18 DIRPORT Caractère 20
19 SVEPORT Caractère 20
20 IMPUPORT Caractère 20
21 DATELIV Date 8 Crois.
22 HEURELIV Caractère 8
23 DELAI Caractère 15
24 EMETTEUR Caractère 40
25 DATPOSTE Date 8
26 IDDESTI Caractère 10
27 CIVDESTI Caractère 4
28 NOMDESTI Caractère 30
29 PRENDESTI Caractère 20
30 DIRDESTI Caractère 20
31 TYPERECO Caractère 20
32 OBSERV Caractère 60
** Total ** 532

pour le bouton :
activebouton=.f.

if modedit="MODIF"
select destinat1
set order to iddesti
seek thisform.txtidenreg.value
if !eof()
m.nomenregis=destinat1.nom
m.prenenreg=destinat1.prenom
m.civenreg=destinat1.civilite
else
thisform.txtnomenregis.value=space(20)
m.nomenregis=space(20)
m.prenenreg=space(20)
m.civenreg=space(4)
endif
select recomman
gather memvar
modedit="CONSULT"
activebouton=.t.
unlock
endif

if modedit="AJOUT"
with thisform
if !empty(.txtidrecomm.value) .and. !empty(.txtidenreg.value) .and. !empty(.txtemetteur.value) .and. !empty(.combo1.value)
.txtdatenreg.value=date()
.txtheurenreg.value=time()
select destinat1
set order to iddesti
seek thisform.txtidenreg.value
if !eof()
m.nomenregis=destinat1.nom
m.prenenreg=destinat1.prenom
m.civenreg=destinat1.civilite
else
thisform.txtnomenregis.value=space(20)
m.nomenregis=space(20)
m.prenenreg=space(20)
m.civenreg=space(4)
endif
select recomman
seek .txtidrecomm.value
if eof()
insert into recomman from memvar
go bottom
modedit="CONSULT"
activebouton=.t.
thisform.refresh
else
messagebox("Id du recommandé déjà existant")
.txtidrecomm.setfocus
endif
else
if empty(.txtidrecomm.value)
messagebox("Veuillez remplir l'identifiant du recommandé")
.txtIdrecomm.setfocus
else
if empty(.txtidenreg.value)
messagebox("Veuillez remplir l'identifiant du préposé")
.txtidenreg.setfocus
else
if empty(.txtemetteur.value)
messagebox("Veuillez remplir l'émetteur du recommandé")
.txtemetteur.setfocus
else
if empty(.combo1.value)
messagebox("Veuillez remplir la direction du destinataire")
.combo1.setfocus
endif
endif
endif
endif
endif
endwith
endif

if modedit="CHERCHER"
vcritere=""
with thisform

vcritere=vcritere+iif (!empty(.txtdatenreg.value) , '.and. datenreg={^' + right(dtoc(.txtdatenreg.value),4) +'-'+ subs(dtoc(.txtdatenreg.value),4,2) +'-'+ left(dtoc(.txtdatenreg.value),2) +'}' , "")
vcritere=vcritere+iif (!empty(.txtheurenreg.value), '.and. heurenreg="' + alltrim(.txtheurenreg.value) +'"' , "")
vcritere=vcritere+iif (!empty(.txtidenreg.value) , '.and. idenreg="' + alltrim(.txtidenreg.value) +'"' , "")
vcritere=vcritere+iif (!empty(.txtnomenregis.value), '.and. nomenregis="'+ alltrim(.txtnomenregis.value)+'"' , "")
vcritere=vcritere+iif (!empty(.txtidrecomm.value) , '.and. idrecomm="' + alltrim(.txtidrecomm.value) +'"' , "")
vcritere=vcritere+iif (!empty(.txtemetteur.value) , '.and. emetteur="' + alltrim(.txtemetteur.value) +'"' , "")
vcritere=vcritere+iif (!empty(.txtdatposte.value) , '.and. datposte={^' + right(dtoc(.txtdatposte.value),4) +'-'+ subs(dtoc(.txtdatposte.value),4,2) +'-'+ left(dtoc(.txtdatposte.value),2) +'}' , "")
vcritere=vcritere+iif (!empty(.combo1.value) , '.and. dirdesti="' + alltrim(.combo1.value) +'"' , "")
vcritere=vcritere+iif (!empty(.txtnom.value) , '.and. nomdesti="' + alltrim(.txtnom.value) +'"' , "")
vcritere=vcritere+iif (!empty(.txtprenom.value) , '.and. prendesti="' + alltrim(.txtprenom.value) +'"' , "")
vcritere=vcritere+iif (!empty(.combo2.value) , '.and. typereco="' + alltrim(.combo2.value) +'"' , "")
vcritere=vcritere+iif (!empty(.txtobserv.value) , '.and. observ="' + alltrim(.txtobserv.value) +'"' , "")

endwith
if vcritere=".and."
vcritere=subs(vcritere,7)
endif
if !empty(vcritere)
locate for &vcritere
if eof()
modedit="CONSULT"
messagebox("Aucune correspondance")
go bottom
activebouton=.t.
else
modedit="FILTRE"
set filter to &vcritere
count to nbtrouve
go bottom
scatter memvar
thisform.bdebut.enabled=.t.
thisform.bprecedent.enabled=.t.
thisform.bsuivant.enabled=.t.
thisform.bchercher.enabled=.f.
thisform.bfin.enabled=.t.
thisform.bmodifier.enabled=.f.
thisform.brequete.enabled=.f.
thisform.bajouter.enabled=.f.
thisform.bok.enabled=.f.
thisform.txtdatenreg.enabled=.f.
thisform.txtheurenreg.enabled=.f.
thisform.txtidenreg.enabled=.f.
thisform.txtnomenregis.enabled=.f.
thisform.txtidrecomm.enabled=.f.
thisform.txtemetteur.enabled=.f.
thisform.txtdatposte.enabled=.f.
thisform.combo1.enabled=.f.
thisform.txtnom.enabled=.f.
thisform.txtprenom.enabled=.f.
thisform.combo2.enabled=.f.
thisform.txtobserv.enabled=.f.
endif
thisform.refresh()
else
modedit="CONSULT"
endif
*activebouton=.t.
endif

if activebouton
thisform.bdebut.enabled=.t.
thisform.bprecedent.enabled=.t.
thisform.bchercher.enabled=.t.
thisform.bsuivant.enabled=.t.
thisform.bfin.enabled=.t.
thisform.bmodifier.enabled=.t.
thisform.brequete.enabled=.t.
thisform.bajouter.enabled=.t.
thisform.bok.enabled=.f.

thisform.txtdatenreg.enabled=.f.
thisform.txtheurenreg.enabled=.f.
thisform.txtidenreg.enabled=.f.
thisform.txtnomenregis.enabled=.f.
thisform.txtidrecomm.enabled=.f.
thisform.txtemetteur.enabled=.f.
thisform.txtdatposte.enabled=.f.
thisform.combo1.enabled=.f.
thisform.txtnom.enabled=.f.
thisform.txtprenom.enabled=.f.
thisform.combo2.enabled=.f.
thisform.txtobserv.enabled=.f.
endif
Merci pour tes réponses.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
michelatoutfox Messages postés 828 Date d'inscription mardi 5 octobre 2004 Statut Membre Dernière intervention 7 mai 2013 1
23 avril 2009 à 12:05
Bonjour,

une première remarque: si tes tables étaient rattachées à un database (un dbc), et si elles avaient des clés primaires, et si elles étaient liées par des rèles d'intégrité référentielle appuyées sur les liens primary keys/foreign keys, alors tu n'aurais jamais le problème que tu évoques.

admettons que tu ne peux pas modifier les structures de tes tables.
commence par déclarer tes variables en LOCAL dans ce code, afin de les isoler proprement (en Fox, une variable non déclarée est créée en PRIVATE, et tu peux donc récupérer une valeur qui a été affectée dans une procédure appelante). profites-en pour remplacer tes seek... if!eof() par des indexseek (regarde dans l'aide la syntaxe complete de cette commande). remplace tes scatter memvar par des scatter to array en nommant chaque array de façon différente, tu feras des gather from.. en étant certain de récupérer les variables que tu veux!

ensuite, la première chose à faire est de mettre un point d'arret au début de ce code, et de vérifier ce qui se passe au débogueur. serait-il possible que tu ne sois pas dans le mode que tu attends (je veux dire en ajout quand tu penses être en modif)? si tu suspecte un déplacement possible du pointeur d'enregistrement, met un RECNO() dans les espion du débogueur et surveille-le au fur et à mesure que on code se déroule.

et quand on aura réglé ce problème, tu pourras regarder l'utilisation de la mise en mémoire tampon et du tableupdate(), pour ne plus avoir à gérer manuellement tes lock/unlock. c'est dommage d'avoir VFP6 et de l'utilisr comme du FPW2.6
0
Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009
28 avril 2009 à 12:06
Bonjour,

J'ai suivi tes recommandations et au debogueur mes variables affichent bien la valeur attendue, recno() n'a pas bougé sur la table concernée. Il faut dire que le phénomène se produit de façon aléatoire donc difficilement reproductible.

Vois-tu autre chose ?
Merci pour toutes tes réponses.
0
michelatoutfox Messages postés 828 Date d'inscription mardi 5 octobre 2004 Statut Membre Dernière intervention 7 mai 2013 1
1 mai 2009 à 23:34
vraiment aléatoire? exactement dans les mêmes conditions?
0
Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009
2 mai 2009 à 06:12
Cela ne s'est pas encore reproduit avec les modifications apportées, il est vrai que ca arrive tous les 100-150 modifs environ (difficile à estimer) dans l'ancienne configuration.
0
michelatoutfox Messages postés 828 Date d'inscription mardi 5 octobre 2004 Statut Membre Dernière intervention 7 mai 2013 1
3 mai 2009 à 18:07
on attend que ça se reproduise pour essayer de comprendre quelle(s) conditions existent à ce moment-là?

En relisant ton code, je ne vois pas à quel moment tu lock, et si tu vérifies que cette demande de verrou est bien réalisée.
0
Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009
3 mai 2009 à 18:44
le lock se fait dans le bouton modifier du formulaire, si le test est ok je dévérouille les champs pour autoriser la saisie, sinon j'affiche une fenetre avertissant l'utilisateur.
0
michelatoutfox Messages postés 828 Date d'inscription mardi 5 octobre 2004 Statut Membre Dernière intervention 7 mai 2013 1
4 mai 2009 à 09:02
Encore quelques points à vérifier:

le seek du mode MODIF est peut-être incorrect (voir le SET EXACT et SET NEAR)

quelle est la portée de la variable Modedit, où est-elle déclarée, initialisée, modifiée

penser à réinitialiser les variables après le gather
0
Etienne77 Messages postés 7 Date d'inscription mercredi 1 octobre 2008 Statut Membre Dernière intervention 6 mai 2009
6 mai 2009 à 08:57
Pour aller au plus simple, je vais mémoriser la position de l'enregistrement à modifier, et avant de faire le gather je fais un go position.
Cela devrait résoudre le problème.

Merci pour tout.
0
Rejoignez-nous