2009-07-10 10 views
0

Le programme principal est donc en C#. Insertion de nouveaux enregistrements dans une table de base de données VFP. Il prenait trop de temps pour générer le prochain ID pour l'enregistrement viaInsertion VFP, mise à jour de l'index

select max(id)+1 from table 

, donc je mets ce code dans une dll de compilation dans VFP et vous appelle cet objet COM via C#.

L'objet COM renvoie le nouvel ID à environ 250 ms. Je viens ensuite de faire une mise à jour via OLEDB. Le problème que j'ai est que, après l'objet COM renvoie l'ID nouvellement inséré, je ne trouve pas immédiatement de C# via le OLEDB

select id form table where id = *newlyReturnedID* 

retours 0 lignes arrière. Si j'attends une période inconnue, la requête retournera 1 ligne. Je peux seulement supposer qu'il retourne 0 lignes immédiatement parce qu'il n'a pas encore ajouté l'ID nouvellement créé dans l'index et donc le select ne peut pas le trouver.

Est-ce que quelqu'un d'autre a déjà rencontré quelque chose de similaire? Si oui, comment l'avez-vous géré?

DD

Répondre

4

Avertissement: votre code est défectueux dans un environnement multi-utilisateur. Deux personnes peuvent exécuter la requête en même temps et obtenir le même ID. L'un d'eux échouera sur l'INSERT si la colonne a une clé primaire ou candidate, ce qui est une bonne pratique pour les champs clés.

Ma recommandation est soit d'avoir l'ID soit un champ entier auto-incrémentant (je ne suis pas un fan d'entre eux), ou mieux encore, créer une table de clés. Chaque enregistrement dans la table est pour une table qui obtient des clés assignées. J'utilise la 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 la suivante:

FONCTION NextCounter (tcAlias)

LOCAL lcAlias,; lnNextValue,; lnOldReprocess,; lnOldArea

lnOldArea = SELECT()

SI PARAMETRES() lcAlias ​​= ALIAS()

IF CURSORGETPROP ("SourceType") = DB_SRCLOCALVIEW * - Tentative d'obtenir la table de base lcAlias ​​= inférieur (CURSORGETPROP ("Tableaux")) lcAlias ​​= substr (lcAlias, AT ("!", lcAlias) + 1) ENDIF AUTRE lcAlias ​​= BAS (tcAlias) ENDIF

lnOrderNumber = 0 lnOldReprocess = SET ('RETRAITER')

* - presse verrouillage jusqu'à ce que l'utilisateur Esc SET RETRAITER AUTOMATIQUE POUR

IF USED ("countergenerator") UTILISATION eventmanagement!countergenerator IN 0 SHARED ALIAS countergenerator ENDIF

SELECT countergenerator

IF SEEK (inférieur (lcAlias), "countergenerator", "touche c") IF RLOCK() = lnNextValue countergenerator.iValue REMPLACER countergenerator.iValue WITH countergenerator.iValue + 1 UNLOCK ENDIF ELSE * Créez le nouvel enregistrement avec la valeur de départ. CONTEND BLANK IN contre-générateur MEMOIRE MEMOIRE SCATTER m.cKey = LOWER (lcAlias) m.iValue = 1 m.mNote = "Créé automatiquement par la procédure stockée". m.tUpdated = DATETIME() GATHER MEMVAR MEMO

IF RLOCK() = lnNextValue countergenerator.iValue REMPLACER AVEC countergenerator.iValue countergenerator.iValue + 1 UNLOCK ENDIF ENDIF

SELECT (lnOldArea) SET POUR RETRAITER lnOldReprocess

RETOUR lnNextValue ENDFUNC

Le RLOCK() s'assure qu'il n'y a pas de conflit pour les enregistrements et est assez rapide pour ne pas geler le processus. C'est beaucoup plus sûr que l'approche que vous prenez actuellement.

Rick Schummer
VFP MVP

0

VFP doit FLUSH ses WorkAreas.