Insertion VFP, mise à jour de l'index
-
12-09-2019 - |
Question
Le programme principal est donc en C#.Insertion de nouveaux enregistrements dans une table de base de données VFP.La génération du prochain identifiant de l'enregistrement via
select max(id)+1 from table
, j'ai donc mis ce code dans une DLL de compilation dans VFP et j'appelle cet objet COM via C#.
L'objet COM renvoie le nouvel ID dans environ 250 ms.Je fais ensuite simplement une mise à jour via OLEDB.Le problème que j'ai est qu'une fois que l'objet COM a renvoyé l'ID nouvellement inséré, je ne peux pas le trouver immédiatement à partir de C# via OLEDB.
select id form table where id = *newlyReturnedID*
renvoie 0 lignes en arrière.Si j'attends une période inconnue, la requête renverra 1 ligne.Je ne peux que supposer qu'il renvoie 0 ligne immédiatement car il n'a pas encore ajouté l'ID nouvellement créé dans l'index et donc la sélection ne peut pas le trouver.
Quelqu'un d'autre a-t-il déjà rencontré quelque chose de similaire ?Si oui, comment l’avez-vous géré ?
DD
La solution
Avertissement:votre code est défectueux dans un environnement multi-utilisateurs.Deux personnes pourraient exécuter la requête en même temps et obtenir le même identifiant.L'un d'eux échouera lors de l'INSERT si la colonne possède une clé primaire ou candidate, ce qui constitue une bonne pratique pour les champs clés.
Ma recommandation est soit que l'ID soit un champ entier à incrémentation automatique (je n'en suis pas fan), soit, mieux encore, de créer une table de clés.Chaque enregistrement de la table concerne une table à laquelle des clés sont attribuées.J'utilise une structure similaire à celle-ci :
Structure for: countergenerator.dbf Database Name: conferencereg.dbc Long table name: countergenerator Number of records: 0 Last updated: 11/08/2008 Memo file block size: 64 Code Page: 1252 Table Type: Visual FoxPro Table Field Name Type Size Nulls Next Step Default ---------------------------------------------------------------------------------------------------------------- 1 ccountergenerator_pk Character 36 N guid(36) 2 ckey Character (Binary) 50 Y 3 ivalue Integer 4 Y 4 mnote Memo 4 Y "Automatically created" 5 cuserid Character 30 Y 6 tupdated DateTime 8 Y DATETIME() Index Tags: 1. Tag Name: PRIMARY - Type: primary - Key Expression: ccountergenerator_pk - Filter: (nothing) - Order: ascending - Collate Sequence: machine 2. Tag Name: CKEY - Type: regular - Key Expression: lower(ckey) - Filter: (nothing) - Order: ascending - Collate Sequence: machine
Maintenant, le code de la procédure stockée dans le DBC (ou dans un autre programme) est le suivant :
FONCTION NextCounter(tcAlias)
LOCAL lcAlias, ;lnValeurNext, ;lnOldReprocess, ;lnOldArea
lnOldArea = SELECT()
SI PARAMETERS() < 1 lcAlias = ALIAS()
SI CURSORGETPROP(« SOURCETYPE ») = DB_SRCLOCALVIEW *-- Tentative d’obtenir la table de base lcAlias = LOWER(CURSORGETPROP(« TABLES »)) lcAlias = SUBSTR(lcAlias, AT(« ! », lcAlias) + 1) ENDIF AUTRE lcAlias = LOWER(tcAlias) ENDIF
lnOrderNumber = 0 lnAncienRetraitement = SET('REPROCESS')
*-- Verrouiller jusqu’à ce que l’utilisateur appuie sur Échap DÉFINIR LE RETRAITEMENT SUR AUTOMATIQUE
SI! USED(« contre-générateur ») USE EventManagement !countergenerator IN 0 SHARED ALIAS countergenerator ENDIF
Contre-générateur SELECT
IF SEEK(LOWER(lcAlias), « countergenerator », « ckey ») SI RLOCK() lnNextValue = contregénérateur.iValue REMPLACER le contregénérateur.iValue PAR le compteur générateur.iValue + 1 OUVRIR ENDIF AUTRE * Créez le nouvel enregistrement avec la valeur de départ.AJOUTER UN ESPACE VIDE DANS le compteur MÉMO MEMVAR DISPERSÉ m.cClé = LOWER(lcAlias) m.iValue = 1 m.mNote = « Créé automatiquement par procédure stockée. » m.tMis à jour = DATETIME() RASSEMBLER LE MÉMO MEMVAR
SI RLOCK() lnNextValue = contregénérateur.iValue REMPLACER le contregénérateur.iValue PAR le compteur générateur.iValue + 1 OUVRIR ENDIF ENDIF
SÉLECTIONNER (lnAncienZone) DÉFINIR RETRAITEMENT SUR lnOldReprocess
RETURN lnValeurSuivante ENDFUNC
Le RLOCK() garantit qu'il n'y a pas de conflit pour les enregistrements et est suffisamment rapide pour ne pas gêner le processus.C'est bien plus sûr que l'approche que vous adoptez actuellement.
Rick Schummer
MVP VFP
Autres conseils
VFP doit VIDER ses WorkAreas .