Newsgroup: it.comp.appl.access
Titolo: locking personalizzato

Ho creato un sistema di locking per una tabella documenti.
I client che leggono un documento inseriscono in un attributo della tabella
documenti il loro nome.
Ggli altri client quando leggono il documento si accorgono che c'è un altro
utente quindi che possiede quel documento e capiscono che il documento è in
sola lettura.
Attualmente però se il documento viene sbloccato non accade niente, cioè gli
utenti bloccati devono provare a rileggere il documento per capire che sono
stati sbloccati.
Ho pensato che avrei potuto rileggere periodicamente il documento dagli
utenti bloccati ma mi sembra troppo oneroso in termini di banda.
Non c'è una soluzione efficiente?

"Mangini" <t.ma...@LEVAtiscali.it> ha scritto
nel messaggio
news:ch4l3b$5po$1...@lacerta.tiscalinet.it...

 Chiunque è in lettura apre il record in maschera
singola??
private sub Fom_load()
me.InLettura = -1
end sub
Privatesub form_unLoad()
me.InLettura = 0
end sub
Massimialino

Mangini ha scritto:

Il primo che visualizza un 'documento' (un record della tabella) sul suo
schermo deve consentire agli altri di leggerlo ma impedire di modificarlo?
O è il primo che inizia a modificare un record che deve impedire agli
altri di modificarlo a loro volta?
Namor
-- 
namor at inwind punto it
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 altri di modificarlo a loro volta?
no, naturalmente sarebbe meglio, ma mi basta quello che hai detto sopra,
però in modo più efficiente che ripetere ciclicamente la lettura usando
form_timer.
io mi aspettavo una gestione ad eventi per queste cose ma non c'è.
Se facessi la lettura ciclica dovrei cercare di essere efficiente il più
possibile, ma penso sia meglio che l'utente pigi un pulsante rileggi
documento.

 si, attualmente funziona così.


E invece è molto più facile il secondo perchè Access lo gestisce
nativamente. Da Access 2000 in poi è disponibile il blocco a livello di
record e non più solo a livello di pagina.
Vai su Strumenti/Opzioni, scheda Avanzate e attiva "Apri database
utilizzando blocco a livello di record". Poi nelle proprietà della
maschera nella scheda Dati imposta "Blocco record" a "Record modificati",
poi premi F1 e leggiti l'help. Chiudi e riapri il database.
Adesso se più utenti accedono allo stesso record, il primo che inizia a
modificarlo lo blocca e gli altri vedranno un simbolo di "divieto" sul
selettore record ad indicare che quel record è in fase di modifica da
qualcun'altro. Quando finisce di modificarlo e lo salva il blocco viene
rilasciato, e i dati dovrebbero aggiornarsi in automatico sugli schermi
degli altri utenti.
Fai qualche prova. Non ti serve nemmeno lavorare in rete, basta aprire due
o tre volte lo stesso db sul tuo PC.


 Namor
ti ringrazio ma già lo sapevo e non ho usato quel tipo di blocco perché non
andava bene nel mio caso che non ho spiegato in tutti i dettagli.
allora ti spiego che il documento è una fattura e che devo bloccare anche le
righe quando blocco una fattura, cosa che secondo me con i tipi di blocco
che access gestisce automaticamente non si può fare in modo "nativo" perché
le righe sono in un'altra tabella.
ci sono altre motivazioni per cui non mi andava bene il blocco di access, ad
esempio io dico chi è l'utente che ha bloccato la fattura,ecc.

Mangini ha scritto:


So che in Access XP sono stati introdotti nuovi eventi, chissà se ce n'è
uno per questa esigenza? Un evento che ti dica quando il record è dirty su
un'altra macchina ti consentirebbe di bloccare anche la sottomaschera.
Il metodo che usi va bene, può funzionare, l'ho usato anch'io una volta.
Puoi fare una function Blocca(ID, nome) che richiami sull'evento current
della maschera. La function si incarica di bloccare il record se lo trova
libero, o di mettere maschera e sottomaschera in sola lettura magari
rendendo visibile un'etichetta di avviso che dice chi sta usando il
record. Per sapere quando il record si libera puoi continuare a richiamare
la function blocca sull'evento timer ogni 1-2 secondi o più.
Sorgono dei problemi: se un utente apre un record e poi va via lasciando
il PC, quel record sarà bloccato per ore. Io avevo previsto un autoclose
della maschera se non utilizzata per più di un certo tempo. O puoi
lasciare le maschere sempre bloccate e consentire la modifica solo quando
si preme un pulsante "Modifica". Ciò ti consente di bloccare i record
quando qualcuno richiede di modificarli e non quando li vuole solo
visualizzare. 
Altro problema è il modo di fare il test per vedere se il record è libero.
Come lo fai? 
Altro ancora è un eventuale crash dell'applicazione, che lascerebbe il
record bloccato anche se nessuno più lo sta usando. In questo caso devi
prevedere una procedura per forzare lo sblocco, magari registrando la
forzatura in un file di log.


 Come lo fai?
ho detto che uso il nome utente come marca per indicare se il documento è
bloccato o no.
gli altri "oggetti" in relazione col documento sono accessibili sono da quel
documento, quindi possono essere bloccati solo insieme a lui.

 documento, quindi possono essere bloccati solo insieme a lui.
Intendevo proprio come funziona il codice che controlla se il record è
libero ed eventualmente lo blocca.
Se è una cosa in due tempi del tipo:
  1. leggi il campo "blocco" del record
  2. scrivi il nome utente nel campo
è soggetto al vecchio problema del test&set in multiutenza che si verifica
quando due utenti accedono quasi contemporaneamente allo stesso record:
L'utente A legge il campo "blocco" del record e lo trova libero.
Nel frattempo l'utente B legge il campo, dopo A ma prima che A abbia salvato
il suo nome.
B trova il record libero perchè A non ha ancora salvato il suo nome.
A salva il suo nome.
B salva il suo nome sovrascrivendo A.
Hai due utenti in modifica contemporanea sullo stesso record.
Namor

 Hai due utenti in modifica contemporanea sullo stesso record.
Ci sarebbe voluta una transazione isolata, cosa che in access non c'è,
nonostante esista la proprietà "isolateODBCtrans".
comunque quello che dici lo evito perché appena l'utente apre il documento
in lettura io (A) apro il recordset in modalità pessimistic e faccio .edit
(dao)  nonostante voglia solo leggere il campo "blocco" del record.
Quindi anche se A non ha ancora scritto la marca, ha comunque bloccato il
record.
Naturale che B esegue lo stesso codice di A.

 Naturale che B esegue lo stesso codice di A.
Si, può andare se gli aggiungi una gestione degli errori, perchè il
problema della lettura contemporanea rimane, entrambi potrebbero leggere
assieme e credere che il record è libero, ma quando il secondo tenterà di
fare il .edit sarà generato un errore.
Altro metodo potrebbe essere una query
UPDATE tabella SET blocco=nome WHERE ID=... and blocco is null;
Se blocco è vuoto lo imposta altrimenti no.
Se la esegui da DAO hai la possibilità di testare la proprietà
recordsaffected per vedere se il record era libero o no.
In vba con un'unica riga (qry.execute) viene fatto sia il test che la
scrittura del nome. Non so poi come si comporta Jet nell'esecuzione della
query, se spezza in due tempi test/scrittura e se possa dare o meno lo
stesso problema. Non credo che troverai in rete dettagli sul funzionamento
interno di Jet nè di Access quindi con questo metodo non ci sarà mai la
certezza assoluta di un corretto funzionamento.
dim qry as querydef
set qry=...
qry.execute
if qry.recordsaffected>0 then
  'ha bloccato il record
else
  'non ha bloccato il record
end if
