Newsgroup: it.comp.lang.delphi
Titolo: Generazione ID

Ciao a tutti.
Sto sviluppando un software che gira in locale, basato su ClientDataSet (e
quindi base dati xml).
Non avendo a disposizione un dbms, vorrei qualche consiglio riguardo la
generazione di ID da utilizzare come chiave primaria dei records. Siete a
conoscenza di qualche buon algoritmo che fa al caso mio?
Grazie,
Luca.

"LucaP" ha scritto nel messaggio

Le API di generazione dei GUID. La generazione di un GUID ti garantisce
senza ombra di dubbio l'univocità dell'ID
Se non erro ci sono anche degli esempi d'uso nei demo di Delphi.
Ciao,
Gianluca.


Open Delphi Manual (
http://groups.yahoo.com/group/delphi_open_manual/
)

 senza ombra di dubbio l'univocità dell'ID
si ma sono 38 (o 34?) byte per record!!
Ciao, Sandro

 si ma sono 38 (o 34?) byte per record!!
Per l'esattezza 38 (ma credo possa essere rappresentato anche con meno
cifre).
In effetti sono un pò tantini ma, visto che si parlava di salvare su XML, ho
immaginato che la mole di dati non fosse significativa. A questo punto
preferirei usare qualche byte in piu' sull'archivio, ma alleggerire (e di
molto) tutta l'elaborazione legata al generatore dell'ID.
Nel caso in cui si decidesse di adottare ad esempio un contatore in un file
separato, sarebbe necessario aggiungere sia il codice per la generazione che
quello di controllo per verificare e risolvere piu' o meno automaticamente
anomalie (il file system purtroppo non può essere assoggettato a commitment
control, quindi in taluni casi potresti avere delle inconsistenze).
Con un ID come un GUID con un unica istruzioni viene generato un numero con
la garanzia di essere univoco e non c'e' necessita' di occuparsi d'altro.
Ovviamente in relazione alla mole di dati.
Ciao,
Gianluca.

control, quindi in taluni casi potresti avere delle inconsistenze
Non sapevo di questa cosa: in pratica stai dicendo che non e' possibile
forzare con qualche API di sorta la scrittura dei dati sul disco fisso ?
-- 
Morde. 
(
mo...@despammed.com
)

 forzare con qualche API di sorta la scrittura dei dati sul disco fisso ?
Quel tipo di forzatura ritengo possa essere eseguito... almeno credo.
Io mi riferivo all'esempio di usare un generatore di ID basandosi su un
contatore in file esterno.
Generalmente, supponendo di lavorare con un qualunque database avresti due
strutture:
- la tabella contenente i dati veri e propri, strutturata in modo che la
chiave primaria sia un progressivo generato da codice;
- la tabella contenente i progressivi.
Il programma dovrebbe essere strutturato in modo da generare un nuovo id
prendendo l'ultimo (o il prossimo) dalla tabella dei contatori. Al
salvataggio del record di dati, per evitare inconsistenze, sarebbe opportuno
creare una transazione in modo da salvare entrambi i record (il nuovo di
dati e l'aggiornato dei contatori)  oppure effettuare il rollback
dell'intera operazione.
Inoltre, se qualcuno dovesse accidentalmente decrementare il contatore,
evidentemente l'errore che se ne gererebbe di chiave duplicata permetterebbe
di far scaturire delle procedure di controllo, ma mai di avere dei dati
inconsistenti. Ovvio che se qualcuno lo incrementa, saltano dei numeri, ma
il problema si porge solo nel caso in cui i progressivi debbano essere
continui.
Se invece il tutto viene eseguito piu' o meno manualmente utilizzando files
di testo, il codice da scrivere si moltiplica, se non altro solo per
riuscire a tenere allineati i dati. Naturalmente anche in questo caso
entrano in gioco due entità:
- il file di dati;
- il file con il contatore.
Dovendo scrivere dei record in un file di testo, tutti univoci, ed
utilizzando un contatore memorizzato in un altro file di testo, imho,
potrebbero esserci i seguenti problemi:
- salvo il record ma per qualche oscura ragione non viene aggiornato il
contatore: la volta successiva riutilizzo lo stesso numero di contatore
(altrimenti devo farmi tutto il controllo a mano perche' su file di testo
non mi darà mai chiave duplicata);
- la modifica manuale ed accidentale del file di testo potrebbe avvenire con
probabilità maggiore rispetto alla modifica di una record in una tabella;
- il controllo di chiave duplicata deve praticamente essere effettuato
manualmente ad ogni inserimento di nuovo record.
Da qui il rischio di quelle che io chiamo inconsistenze, dovute
principalmente all'impossibilità di considerare come atomica la transazione
composta da salvataggio del nuovo record ed aggiornamento del relativo
contatore. A meno che non ci sia qualcosa che non so' e non sono a
conoscenza di API o funzionalità che permettano questo; in questo caso
allora ovviamente buona parte del mio ragionamento non è valida. In tal caso
mi documento, che è meglio ;-).
E di conseguenza nasce l'idea, dato per assodato che l'ID non
necessariamente sia univoco, di utilizzare un algoritmo di generazione ed il
più immediato a mio avviso è quello di generazione del GUID.
Ciao.
Gianluca.

 del GUID.
Ma anche il GUID non è progressivo, giusto?
Inoltre, come si fa a garantire che la chiave generata, spostando i file
da una macchina all'altra, sia effettivamente univoca?
Certo, le combinazioni di GUID ottenibili sono tante, però il fattore
"sfortuna" non è trascurabile. :-)


 "sfortuna" non è trascurabile. :-)
Il GUID non è progressivo, però stando alla documentazione, la coCreateGUID
genera un identificatore di 128bit univoco in senso assoluto ed irripetibile
sia sulla stessa macchina che su macchine diverse. Ed essendo il concetto di
GUID fondamentale per l'identificazione di qualsiasi oggetto COM locale o in
rete, dovrebbe essere un'affermazione abbastanza certa. :-)
Da qui appunto il mio ragionamento: se uso un progressivo devo scrivere del
codice per memorizzarlo e per tenerlo allineato, se uso un algoritmo di
generazione devo trovarlo, scriverlo e testarlo. Con la coCreateGUID scrivo
una riga di codice e son sicuro che funziona su tutte le macchine. E' un pò
un modo per ottenere il risultato con il minimo sforzo. ;-)
Con l'ovvia e doverosa premessa: in questo specifico caso non devono essere
fondamentali ne la continuità dell'identificatore ne lo spazio occupato
dalla sua rappresentazione.
Ciao,
Gianluca.

un modo per ottenere il risultato con il minimo sforzo. ;-)
Ed e' il piu' appropriato, imvho!, perche' il topic era per l'appunto
realizzarne una gestione su xml, senza avere i giovamenti di un db engine e
cmq non dovendo fare giri strani per avere l'unique id. :-)
-- 
Morde. 
(
mo...@despammed.com
)

 essere un'affermazione abbastanza certa. :-)
Vista la spiegazione approfondita, mi fido. ;-)
Certo che è strana la garanzia che la GUID sia sempre diversa...si
affideranno al fatto che il numero di combinazioni possibili è talmente
elevato da rendere vana qualsiasi possibilità che un numero venga
duplicato?


 duplicato?
Sinceramente non conosco i dettagli dell'algoritmo. In genere uso la
coCreateGUID o, se ne ho necessità in Delphi, la combinazione Shift+Ctrl+G.
Alla base c'è la rilevazione del numero di serie della scheda di rete e
dell'ID del processore (dai PIII in su mi sembra, ma probabilmente un numero
di serie tutti i processori ce l'hanno sempre avuto), oltre alla data e
l'ora di sistema. I primi due elementi già di per se sono univoci, associati
alla data e l'ora di sistema praticamente già sono una buona garanzia di
avere un idenficativo univoco globale. Credo che poi sfrutti anche altro
hardware dotato di numero di serie.
Ciao.
Gianluca.

 venga duplicato?
A dire il vero credo sarebbe sufficiente un Int64 generato con due
chiamate a rand. Ovviamente dopo aver fatto un randomize.
Saluti
Paolo Arosio
-- 
"La dimostrazione dell'esistenza di specie intelligenti nell'universo
 e' che non ci vengono a trovare" [Calvin & Hobbes]