Newsgroup: it.comp.appl.access
Titolo: Un modo per risolvere i conflitti

Se due utenti cercano di modificare lo stesso record,
se ne possono vedere delle belle. Meglio evitare.
Cerca di qua, cerca di la, non ho trovato nulla che
risolvesse realmente in un contesto siffatto
(contesto non modificabile, purtroppo)  :
ogni utente si collega, carica i dati e si disconnette.
Quindi puo' studiare un record anche per ore prima
di prendere una decisione. Nel frattempo un altro
piu' veloce puo' averlo modificato, per cui i dati che
vede l' utente sono ORMAI cambiati, e potrebbe
prendere la decisione sbagliata, oltre al fatto ovvio
che modificando potrebbe sovrascrivere le modiche
fatte dall' altro. Un bel problema insomma, via.
Allora faro' cosi' :
sulla maschera non c'e' il tasto modifica, ma il
tasto "prenota". O giu' di li.
L' utente fa click su quel tasto e scatta una
routine che legge la kiave del record e tenta
di inserirla in una tabella sul server, K (che e'
del tutto indipendente dalla tabella dei dati che
devono essere modificati)  nel suo campo kiave.
Allora a quel punto se un altro utente ha fatto prima
di lui, addirittura lo mando in VIOLAZIONE DI KIAVE,
per cui o ci sta uno, o ci sta l' altro.
Non c'e' cristo che tenga.
A quel punto intercetto l' errore di violazione e avverto
l' utente : "record gia' in modifica, non rompere e prova
piu' tardi" (e magari gli posso pure dire da CHI, se in K
ci metto nome, cognome, telefono e perche' no email
dell' utente che "acchiappa" il record per primo) .
Se invece riesce a inserire la kiave su K, il record e' suo
e non glielo tocca piu' nessuno.
NESSUNO puo' sopravvivere a una violazione di kiave :-)
A quel punto vado sulla tabella server, leggo i dati aggiornati
a quel momento  e glieli sparo in maschera.
poi, il tasto che ha premuto cambia caption e ci scrivo
"modifica". (Se lo preme, modifica e poi toglie la sua kiave da K,
liberando il record).
Appena cambiata la caption, creo un orologio di sistema
con una chiamata alla funzione API settimer( ... ) senza
bisogno di mettere un costoso timer sulla maschera, e apro
una maschera con un conto alla rovescia a numeroni  grossi :
per modificare gli do', diciamo, 2 minuti o 3 o 5 ... Basta che
il tempo sia definito. Senno' il record sarebbe immodificabile
da tutti per sempre, se quello non lo rilascia.
(e magari il tempo si puo' rendere variabile in funzione del
traffico su quella tabella).
Se l' utente in 2 minuti non fa nulla, tramite una chiamata
in call back della settimer ( ...) gli levo la kiave da K , rimetto
la caption del tasto a "prenota" e ammazzo il timer.
E magari sul conto alla rovescia gli scrivo :
tempo scaduto, Prova piu' tardi, forse sarai piu'
fortunato. (scherzo)
Se invece l' utente modifica premendo il tasto, meglio
cosi'' : levo lo stesso la kiave da K. ammazzo il timer e
rimetto il tasto a prenota.
L' unico difetto e' che se per qualsiasi ragione il client
di un utente va in errore (magari putacaso PROPRIO perche'
cade la connessione e/o la rete ... La sfiga regna sovrana, e
in quel caso anche gestendo l' errore, non posso togliere la
kiave da K) la tabella K rimane con la kiave e quando la rete si
ripristina, nessuno potra' modificare quel record.
Pero' in quel caso iper-sfigato si puo' sempre andarci a manina
e cancellare la kiave.
... Ma insomma sono casi piuttosto improbabili.  La rete e la
connessione cade, ma in un mese due volte al massimo.
Macche', anche meno. Spesso non cade per mesi e mesi !
A quel punto l' intervento a manina e' forse la cosa piu'
ragionevole.
Una bella cancellata e via ! E passa la paura.
Che dite, che dite ?

 e cancellare la kiave.
non volendo entrare nel merito del sistema, per utenti che si bloccano non 
devi andare per forza a manina... basta che oltre alla chiave, aggiungi 
l'ora di prenotazione, e ad ogni apertura, fai cancellare a prescindere con 
un sql delete tutti i record della tabella che con un datediff rispetto al 
valore del campo dataoraprenotazione, superano in minuti quelli da te 
precedentemente stabiliti.

 precedentemente stabiliti.
Qualsiasi sia l' utente che entra, dici tu ?
Si. Giusto.
Ma allora a questo punto si puo' mettere anche su richiesta di un
altro utente : chiunque, insospettito dal fatto che un record e'
bloccato, premendo un tasto puo' far partire la query delete.
Come funziona la datediff ? Mi posteresti due linee di codice
per farmi vedere come va scritta concretamente questa query ?

 per farmi vedere come va scritta concretamente questa query ?
Cancello da Tabella1 il record con campo ID avente nel suo campo cmp_Date, 
un valore la cui differenza in minuti con il datetime attuale ( Now() ) è 
superiore a 5 :
DELETE Tabella1.ID, DateDiff("n",[cmp_Date],Now()) AS MinDiff
FROM Tabella1
WHERE (((DateDiff("n",[cmp_Date],Now()))>5));

 WHERE (((DateDiff("n",[cmp_Date],Now()))>5));
... Ottimo.
Ancora una domanda :
Pensi che una query del genere (la chiamo Q, variabile stringa)  possa
essere
tranquillamente eseguita anche dandola in pasto ad una connessione
ADO ?
Ad esempio :
connection.execute Q
Oppure occorre qualche piccolo cambiamento nella sintassi ?

> Che dite, che dite ?
Usa la Tunze e non pensarci più.

 Oppure occorre qualche piccolo cambiamento nella sintassi ?
permettimi, ma mi viene sponaneo domandarti una cosuccia.... da ciò che 
leggo di te, tu non conosci cosa sia un MDE, non conosci un DateDiff, non 
conosci le proprietà di una Form in visualizzazione tabella, ma poi parli di 
Query passanti per ADO e connection, di parametri sulla gestione errori... 
non ti pare un pò strano? ti mancano le basi ma poi cerchi la funzione 
Erl()... non sto capendo molto sulla tua preparazione, e ciò mi fa anche 
tentennare sugli standard di risposta che devo darti... vorrei tararle 
adeguandole al tuo grado di conoscenza per permetterti di comprendere, ma se 
non capisco quello, non so neanche cosa poterti dire e cosa no... dammi un 
indizio ;)
PS. credo che la miglior cosa sia nel tuo caso fare :
Docmd.SetWarnings False
Docmd.RunSQL "....tuo_Sql...."
Docmd.SetWarnings True 

 Docmd.SetWarnings True
Mh, buono. Non sapevo fosse cosi' facile eseguire una query
in access.
Ma con la chiamata alla connessione e' meglio, la controllo meglio
(per una serie di ragioni bla bla bla).

(per una serie di ragioni bla bla bla).
"� meglio" � un parolone... "la controllo meglio" � un'altro parolone 
ancora... cosa vuoi controllare in un SQL che solo una volta lanciato fa ci� 
che ti aspetti senza poterne bloccare gli eventi?... quindi tutto fai tranne 
che controllarlo... tutti i controlli puoi farli solo prima di 
"Docmd.RunSQL..." o di un "connect.execute Q"... � la misma cosa.

Che dite, che dite ?
Di sistemi per la concorrenza ce ne sono tantissimi. Quello dei 'semafori' è
uno dei tanti, ma sposti il problema da una tab all'altra.....e se due utenti
vogliono scrivere la tabella-semaforo contemporaneamente? E se le modifiche si
riflettono sui client con un attimo di ritardo? Tutte cose strane ma non
impossibili......
Se parli di ambiente mdb e di maschere associate, è + che sufficiente il
blocco record in modifica di access (e la conseguente gestione dei 2 errori
che genera in una routine centralizzata). Se parli di SQL server, direi che
non c'è bisogno di nulla, fa tutto lui con il timestamp.
Il metodo 'completo' per le maschere non associate puo essere una cose del
genere (simula il timestamp...): fai una SELECT sul record e apri la maschera
non associata. Fai le tue cose, premi AGGIORNA. Il codice: UPDATE Tabella
set......WHERE (tutti i campi = al vecchio valore della select). Ora sei
SICURISSIMO che il record non abbia subito modifiche......
-- 

 blocco record in modifica di access
Assolutamente no.
Perche' il blocco del record agisce solo durante l' operazione.
E poi col tuo metodo, come so chi si e' impadronito del record ?

 "Docmd.RunSQL..." o di un "connect.execute Q"... la misma cosa.
Se se ... Come no. la "misma" proprio ... ;-)
Prova a gestirci una *transazione* con docmd ...
o a fare recordset disconnessi e salvarteli su disco.
Oppure a metterci in piedi una elaborazione asincrona
multithreading con eventi di avanzamento.
E via cantando. uguale uguale.

E poi col tuo metodo, come so chi si e' impadronito del record ?
No, chi 'ha' il record no......ma se in maschere associate due utenti aprono
lo stesso record (è in lettura/scrittura x entrambi) e lo guardano e basta,
ok, appena uno modifica qcosa, l'altro viene IMMEDIATAMENTE reso snapshot e
non lo puoi toccare!!!! Testato personalmente....quindi mi pare che il
risultato ci sia no?!?
-- 

 E via cantando. uguale uguale.
e vabbè allora dilla tutta... il progetto dillo tutto, altrimenti se parti 
con il "come si fa a trasferire...." uno ti suggerisce il metodo 
principale... poi è ovvio che se cambi lo scenario standard, anche la 
risposta standard cambia direzione... 

e vabbè allora dilla tutta... il progetto dillo tutto, altrimenti >se parti con il "come si fa a trasferire...." uno ti suggerisce il >metodo principale...
Hai ragione,
ma (sinceramente) non volevo annoiarvi piu' dello stretto
necessario.

risultato ci sia no?!?
Si, e' un buon metodo anche questo in effetti.
Ti ringrazio.