Newsgroup: it.comp.lang.delphi
Titolo: Multiutenza su Access

So che gia' dal titolo del messaggio qualcuno potrebbe inorridire, ma
purtroppo io faccio solo quello che mi viene richiesto... :-(
Il problema e' il seguente: ho un certo numero di tabelle in Access, devo
definire un ID univoco per gli elementi delle tabelle, utilizzando ADO per
accedere, ma il programma funziona in multiutenza.
Qualcuno di voi ha idea di come fare?
Se uso i contatori, "perdo il controllo", nel senso che non so come andare a
rileggerli (a meno di "tirare a indovinare"), e non so con precisione quale
sia l'ID corrente durante un'operazione di inserimento (mi serve saperlo per
un sacco di relazioni master-detail tra le tabelle).
Se uso numeri interi, e' lo stesso problema: devo creare una query che
selezioni il max, e aggiunga 1, se il programma e' mono-utente non e' un
problema, ma in caso di multiutenza, comincia a complicarsi.
Potrei usare una tabella "di appoggio" in cui tenere tutti i contatori, e
aggiornarli ogni volta che inserisco un elemento, (come si fa in Cobol), ma
l'operazione di "lettura e scrittura" del contatore deve essere atomica,
altrimenti anche qui c'e' una (minima) probabilita' di conflitti, e non
vorrei rischiare.
Di solito, come si risolve il problema?
Per il momento utilizzo componenti data-aware, ma ho intenzione di toglierli
poco per volta (quando usciro' dalla fase di "prototipo" non ce ne saranno
piu')

Di solito, come si risolve il problema?
E' una bella grana :-((
HAi gia' guardato il tutorial sulla concorrenza di Fabrizio Mancini, in questo
NG ?
-- 
Morde. 
(morde at programmer dot net)

 in questo NG ?
No, ho letto il messaggio ma pensavo che trattasse altre tematiche... gli
daro' sicuramente un'occhiata... grazie.
-- 
Gabriele 'bigmouth', Sestri Levante (GE)
Su Honda Foresight 'fore-divanetto' 250, ---> ő\ň
ex Kymco Heroism 150
'L'utente piu' medio di IHMS' da sondaggio del 2002

1) Versione di delphi?
2) Versione di ado?
3) Versione di Access?
parto dal presupposto che usi D6, Access 2002, ado 2.6 o superiore.
ti consiglio di usare per questo problema un contatore univoco che access
puo generare. adesso non mi ricordo come si chiama il tipo di campo ma lo
individui facilmente. Generea una specie di GUID.
Ma l'id è univoco per tutte le tabelle?
Inoltre lo puoi gestire con le transazioni che avvii a livello di
adoconnection. calcola che si possono gestire fino a 5 transazioni
nidificate, e l'access se non mi sbaglio le supporta.
Inoltre ti consiglio anche di scaricarti il componente tbetteradodataset che
implementa il componente dataset un pochino meglio di quello che viene fatto
dai componenti di delphi nativi.
ciao
fabrizio

Di solito, come si risolve il problema?
Di solito non si risolve ;-)... nel senso che, con db come Access o
Paradox, si evita di usare i contatori o gli autoincrementanti e si
punta alla scrittura del record solo alla fine (ciclando in caso di
key violation).  Con Interbase, la faccenda è ben diversa.
-- 
Andrea Laforgia
Open Delphi Manual
http://groups.yahoo.com/group/delphi_open_manual/

 individui facilmente. Generea una specie di GUID.
numerico o alfanumerico?
Bye
A

 numerico o alfanumerico?
eccolo
{996885EE-C1A2-4E56-970A-C90F99BD4699}
crei un campo contatore e sulle proprietą del campo al posto di intero lungo
metti "ID Replica"
ti crea questo GUID
ciao fabrizio

 {996885EE-C1A2-4E56-970A-C90F99BD4699}
sono molto restio ad usare chiavi primarie alfanumeriche.
In primis sono + lente, poi, se hai delle relazioni master-detail le tabelle
di dettagli devono portarsi dietro una stringa molto lunga x avere un
riferimento al record padre.
In questo caso, 36 caratteri.
Bye
A

 wrote:

Il GUID è sempre alfanumerico: {A8959CF2-CA1E-46C9-8A4A-75FE2BB10746}
(uno bell'e pronto calcolato adesso con CTRL+SHIFT+G in Delphi ;-)
A me fa venire da vomitare l'idea di usarne uno come chiave primaria
;-)


 In questo caso, 36 caratteri.
Io pure se è per questo! Difatti non ho detto che fossero meglio o peggio di
qualcosa ma siccome gli serve un id univoco in tal maniera può essere sicuro
che l'id generato è sicuramente univoco, anche se dovesse poi fare un
rollback della transazione che sta eseguendo. Hai + tranquillità rispetto
agli id numerici a discapito delle prestazioni però.
Fosse per me se non espressamente richiesto non userei ormai + access,
figurati dopo aver conosciuto firebird, chi lo abbandona +. Solo per
oracle.... ;-)) solo per chi ha voglia di pagarlo naturalmente!!
ciao fabrizio

 ;-)
Aspetta...
Dovrei averlne qualcuno qui...
Ah! Eccolo!
Tie'! un bel sacchetto antivomito ..... :))))
A

 oracle.... ;-)) solo per chi ha voglia di pagarlo naturalmente!!
Che papa' Oracle sia il top per gestire quantita disumane di dati, è fuori
discussione.
Ma, avendolo usato, ribadisco che Sybase non è niente male.
Bye
A

 sono molto restio ad usare chiavi primarie alfanumeriche.
In realta' un GUID e' un intero a 128 bit; quella che si vede e' la
rappresentazione in hex.
Non so se esista il tipo in AXS, ma potendo una soluzione e' di generare
una chiave a 64 bit con 2 semplici chiamate a random(MAXINT) (ovv.te
dopo aver chiamato Randomize all'avvio della app). La chiave generata
dovrebbe avere minime collisioni con altre gia' presenti.
Saluti
Paolo Arosio

dovrebbe avere minime collisioni con altre gia' presenti.
Mi vengono i brividi !!


Che papa' Oracle [...]
Non ricordarmelo, sto per reinstallarlo... mi preparo già ai mal di
stomaco ;-)


 In questo caso, 36 caratteri.
In questo caso 16 bytes = 128 bit (si, non sono pochi, comunque e' un po'
diverso)

 Mi vengono i brividi !!
Ti capisco... infatti stavo pensando anch'io se non fosse un tantino troppo
lasciato al caso... Gia' sui GUID la stessa Microsoft non garantisce
l'univocita', ma solo "un'altissima probabilita'" che siano unici (basandosi
sul MAC della scheda di rete, e su altri fattori IMHO discutibili)...
In alternativa, pensavo di utilizzare una tabella per gestire i vari lock e
le chiavi primarie. Una specie di semaforo:
- Inserisco una riga nella tabella, utilizzando '0' per la chiave primaria.
Se riesco a farlo, posso continuare l'inserimento, seleziono il MAX(ID)+1, e
proseguo. Se non riesco, qualcuno sta gia' lavorando sulla stessa tabella e
mi metto in coda. Questo evita i conflitti, ma impedisce 2 inserimenti in
contemporanea sulla tabella, e se l'applicazione si blocca senza cancellare
il lock, non e' piu' possibile lavorare.
- Uso un'altra tabella, con un solo campo. Prima di iniziare calcolo il
MAX(ID)+1, e lo inserisco nella tabella di appoggio. Se riesco, posso
continuare. Se non riesco, aggiungo 1 e riprovo. La stessa tabella puo'
essere usata per tenere traccia delle modifiche effettuate dagli utenti...
un po' macchinoso? Altri svantaggi?
In entrambi i casi ho a disposizione un'operazione atomica: l'inserimento in
tabella, ovvero tutto quello che mi serve per realizzare un semaforo, un po'
grezzo, ma suppongo che funzioni. Niente GUID, contatori o numeri random.

 key violation).  Con Interbase, la faccenda è ben diversa.
Lo so, infatti fosse per me avrei messo FireBird...
Anch'io punterei a scrivere solo alla fine, ma il cliente vuole vedere il
"numero di pratica" su cui sta lavorando fin dall'inizio dell'inserimento (e
non me la sento di dargli torto, mi sembra una cosa intelligente). Anche se
il numero di pratica non e' necessariamente chiave primaria (infatti nel mio
caso non lo e'), la relazione tra i 2 e' molto stretta: anche i numeri di
pratica non possono essere nulli o ripetuti.

contemporanea sulla tabella
Non ha senso: questa non è più multiutenza.  Se devi effettuare un
lock a livello di tabella, ci sono sistemi più semplici per farlo.


pratica non possono essere nulli o ripetuti.
Sono due questioni separate.  Non c'è problema nell'utilizzare la
chiave primaria della tabella come autoincrementante.  Per risolvere
il problema, invece, dell'unicità del numero di pratica, devi
semplicemente costruire un indice secondario e *unico* (cioè senza
ammissione di duplicati) su quel campo.  Essendo un indice unico,
procedi alla generazione del numero di pratica nel modo seguente:
repeat  
  try
    numpratica = max(numpratiche) + 1
    insert numpratica
    restart = false
  except
    if key violation then 
    begin
      restart = true      
    end;      
  end  
until not restart


Non e' alfanumerico, ma esadecimale
Se devi memorizzarlo come stringa, è una chiave alfanumerica.
Esadecimale non vuol dire nulla, è comunque una rappresentazione
alfanumerica.


 lock a livello di tabella, ci sono sistemi più semplici per farlo.
Infatti, cercavo solo un'operazione atomica per realizzare un semaforo...
l'ho trovata, comunque (e' la seconda soluzione che ho scritto).
Ultimamente mi trovo troppo spesso d'accordo con te... sara' il caldo? :-)
:-)

 alfanumerica.
Se devi visualizzarlo come stringa, *diventa* una stringa, ma e' una
rappresentazione esadecimale di un numero a 128 bit, che internamente al
database e' un numero a tutti gli effetti.

 until not restart
E' esattamente quello che ho fatto (vedi messaggio poco piu' in su)... :-)
:-)