Inserimento VFP, aggiornamento indice
-
12-09-2019 - |
Domanda
Quindi il programma principale è in C#.Inserimento di nuovi record in una tabella di database VFP.La generazione dell'ID successivo per il record tramite ha richiesto troppo tempo
select max(id)+1 from table
, quindi inserisco il codice in una DLL di compilazione in VFP e chiamo l'oggetto COM tramite C#.
L'oggetto COM restituisce il nuovo ID in circa 250 ms.Quindi eseguo semplicemente un aggiornamento tramite OLEDB.Il problema che sto riscontrando è che dopo che l'oggetto COM restituisce l'ID appena inserito, non riesco a trovarlo immediatamente da C# tramite OLEDB
select id form table where id = *newlyReturnedID*
restituisce 0 righe indietro.Se aspetto un periodo di tempo sconosciuto, la query restituirà 1 riga.Posso solo supporre che restituisca immediatamente 0 righe perché deve ancora aggiungere l'ID appena coniato nell'indice e quindi la selezione non riesce a trovarlo.
Qualcun altro si è mai imbattuto in qualcosa di simile?Se sì, come hai fatto a gestirlo?
GG
Soluzione
Avvertimento:il tuo codice è difettoso in un ambiente multiutente.Due persone potrebbero eseguire la query contemporaneamente e ottenere lo stesso ID.Uno di questi fallirà sull'INSERT se la colonna ha una chiave primaria o candidata, che è una procedura consigliata per i campi chiave.
Il mio consiglio è di fare in modo che l'ID sia un campo intero con incremento automatico (non ne sono un fan) o, ancora meglio, di creare una tabella di chiavi.Ogni record nella tabella è per una tabella a cui vengono assegnate le chiavi.Utilizzo una struttura simile a questa:
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
Ora il codice per la procedura memorizzata nel DBC (o in un altro programma) è questo:
FUNZIONE NextCounter(tcAlias)
Alias lcLOCALE, ;lnValoresuccessivo, ;lnOldReprocess, ;lnOldArea
lnOldArea = SELEZIONA()
If parametri () <1 lcalias = alias ()
Se CURSORGetProp ("SourceType") = db_srclocalview *- tentativo di ottenere la tabella di base LCALIAS = inferiore (cursorgetProp ("tabelle")) lcALIA (TCALIAS) ENDIF
lNorderNumber = 0 lNoldreProcess = set ('Reprocess')
*- Blocca fino a quando l'utente preme ESC Imposta il ritrattamento su automatico
If! Usate ("controgenerator") usa eventmanagement! Controgeneratore in 0 alias condiviso controgenerator endif
SELEZIONA controgeneratore
Se cerca (inferiore (lcALIAS), "controgeneratore", "ckey") se rlock () lnnextValue = controgenerator.ivalue sostituisci controgenerator.ivalue con controgenerator.vale + 1 scolore else else * crea il nuovo record con il valore iniziale.Appendere il vuoto nel controgeneratore Scatter Memvar Memo M.Ckey = Lower (LCALIAS) M.Vivalue = 1 M.MNote = "Creato automaticamente dalla procedura memorizzata." m.tupdated = datetime () raccogli il memo memvar
Se rlock () lnNextValue = controgeneratore.Vivalue Sostituisci controgenerator.Vivalue con controgenerator.Vivalue + 1 Sblocca ENDIF ENDIF
Seleziona (LNoldarEa) Imposta il ritrattamento su lnorreprocess
Return lnnextValue endfunc
RLOCK() garantisce che non vi siano conflitti per i record ed è sufficientemente veloce da non creare colli di bottiglia nel processo.Questo è molto più sicuro dell’approccio che stai adottando attualmente.
Rick Schummer
MVP del VFP
Altri suggerimenti
FLUSH suoi un'aree .