Newsgroup: it.comp.lang.delphi
Titolo: app DB Client/Server

Ciao a tutti.
E' la prima volta che scrivo un'applicazione gestionale C/S. Scusate,
perciò, la banalità della domanda.
L'app è realizzata con Interbase 6.
Utilizzo, per l'accesso al database, i componenti TIBDatabase,
TIBTransaction e TIBTable.
Il client va a prendersi i dati da un file gdb memorizzato su un PC remoto.
Ho sperimentato il seguente problema: se effettuo una qualsiasi transazione
(ad esempio un Post() ), i dati aggiornati sono visibili solo sul PC dal
quale parte la suddetta operazione, e gli altri continuano ad avere tabelle
"non aggiornate".
Ho provato a chiamare il Refresh(), ma evidentemente, visto che la
situazione non cambia, c'è qualche passaggio da effettuare a monte.
Sapreste aiutarmi?
Grazie mille,
A

metti nei params delle ibtransactions la voce READ_COMMITTED
Bye
A

"non aggiornate".
Le transazioni, in IB, sono per default "read committed", il che
significa che tutto ciò che è nel loro contesto è capace di leggere
SOLO i dati "committed".  Se ci sono due transazioni A e B e sono
state compiute delle operazioni per la transazione A per la quale non
è stato ancora effettuato il commit, la transazione B non è in grado
di leggere quelle informazioni.  Il tuo è comunque uno sbaglio molto
comune di progettazione del programma.  A mio avviso, in un modello
client/server, non dovrebbe essere necessario aggiornare i dati su
ogni postazione.  I dati sono centralizzati, se anche due operatori
stessero "guardando" gli stessi dati, al momento di compiere qualunque
operazione, bisogna verificare che i dati siano ancora coerenti con
quanto visualizzato.  Supponi un caso del genere:
L'utente A entra nel programma ed esamina le scorte di magazzino: le
penne sono 50.
L'utente B entra nel programma ed esamina le scorte di magazzino: le
penne sono 50.
L'utente A dispone, a fronte di quanto osservato, che ne vengano
vendute 30.
L'utente B è fermo a bere un caffè.  Si risveglia e procede anche lui
con la volontà di vendere 30 penne.  
Ovviamente lo stato del magazzino non è più coerente con quanto
l'utente B vede. 
Ovviamente si sarebbe potuto fare in modo che i dati visualizzati per
l'utente B si aggiornassero in tempo reale, dopo l'operazione di A, ma
non è affatto necessario.

 quanto visualizzato.
Intanto grazie ad entrambi.
Andrea: non credo di aver afferrato molto bene il senso del discorso...
Con ciò che hai detto intendi che è un errore aggiornare i dati in tempo
reale?
Grazie
A

Devi fare semplicemente TuaTransizione.CommitRetaining;
Ciao by Enzo
www.scozzaro.it

 Devi fare semplicemente TuaTransizione.CommitRetaining;
Ho interpretato il tuo consiglio impostando la proprietà DefaultAction della
Transaction a TACommitRetaining.
in effetti, empiricamente parlando, ora la transazione viene eseguita sulle
macchine.
Mi aspetterei, ora, che alla fine della transazione venissero generati gli
eventi *TransactionEnd.
Provo a breakpoint-arli ma sembra che non ci passi nemmeno.
A questo punto, posto un po' di codice... chissà che non ci sia qualche
errore...
Form1->Clienti->SetFields(ARRAYOFCONST((StrToInt(Edit1->Text),Edit2->Text,Ed
it3->Text, Edit4->Text, Edit5->Text, Edit6->Text, Edit7->Text, Edit8->Text,
Edit9->Text, Edit10->Text, Edit11->Text, Edit12->Text, Edit13->Text,
Edit14->Text, Updatable)));
                Form1->Clienti->Post();
                if(Form1->IBTransaction1->InTransaction){
                        Form1->IBTransaction1->Commit();
                        Form1->Clienti->Active=true; //dopo la transazione
lo stato di Clienti risulta essere Not Active
                }
Quindi, ricapitolando, effettuo il commit della transazione (l'esecuzione
del quale avviene correttamente, immagino: le spie del router si accendono
per la transazione in corso) e mi aspetterei che, essendo la transazione
attiva, il server se ne accorgesse. ma non sembra essere così.
So che sbaglio. Ne sono sicuro.
Sapreste indicarmi dove?
Grazie mille di nuovo,
A

reale?
Sì, un errore logico, anche perché nessuno mi vieta di pensare che
l'utente possa procedere ad un'operazione nell'intervallo tra un
aggiornamento e l'altro.  In questo caso come tuteli la consistenza
dei dati ? 

 dei dati ?
Uhm... finora ho sempre sviluppato sotto linux sistemi C/S (non database), e
ovviavo a questi problemi rendendo atomiche le operazioni di
lettura/scrittura/update  mediante semafori kernel.
Pensavo che anche con i DB ci fossero gli stessi meccanismi, implementati a
livello di DBMS.
Mi smentisci clamorosamente?
A

Mi smentisci clamorosamente?
In un DBMS le operazioni sulla base dati vengono serializzate dal DB
stesso e la coordinazione tra le transazioni è tutta a carico del
DBMS.  Quello che sto dicendo (in base a ciò che mi è sembrato di
capire) è che non bisogna aggiornare tutti i client che accedono a una
base dati, a seguito dell'operazione di uno di essi.  In ogni caso la
mia constatazione era da corollario al problema principale: le
transazioni agiscono in contesti separati.  Se sono di tipo "read
committed", fino a che non esegui un commit, i dati non vengono
consolidati e non sono visibili tra transazioni diverse.

 consolidati e non sono visibili tra transazioni diverse.
Ok, credo di capire.
In ogni caso, rimane pur sempre il problema di capire perché, volendo
sincronizzare i dati dopo un Transaction->Commit(), e gestendo gli eventi
sul server AfterTransactionEnd e BeforeTransactionEnd, questi due eventi non
vengano mai generati.
Grazie, Andrea
A