ciao Sebastiano
giari ha scritto:
Scenario 1.
Diciamo che quel contatore viene aggiornato da un tasto e non ci sono operazioni intermedie, e se ho interpretato correttamente quello che hai scritto significa che quando premo il tasto di incremento, l'operazione è talmente veloce che se un altro utente preme il tasto incremento andrà in coda e leggerà il mio incremento.
lo stesso vale per "te", nel senso che se altri hanno gia' fatto "+1", quando tu premi il tasto, il risultato finale sara' "+1 [dell'altro] +1 [tuo]"
e' il classico principio di utilizzo dei dbms...
considera la prenotazione di un biglietto aereo... tu ti loggi a T0, fai le tue "cose", finalmente scegli il posto, e al tempo T3 finalmente spingi <Conferma>...
io entro al tempo T1... l'unico posto disponibile e' ancora libero (tu non l'hai ancora confermato), ed io lo posso vedere... a T2 io confermo...
quando tu in T3 confermi, non ci sara' piu' disponibilita' e non ti restituiscono 404 ma "posti esauriti"... oppure se c'e' ancora disponibilita' e la scelta del posto NON FOSSE individuale ma semplicemente di "1 posto", allora semplicemente ti verra' assegnato questo "1 posto" e la disponibilita' continuera' a diminuire :D
L'altro scenario è se io visualizzo il contattore e l'ho fa anche un altro utente (quindi visualizzano lo stesso dato) e l'altro utente aggiorna, io non saprò mai della variazione se non gestisco la concorrenza ottimistica.
ci sono funzionalita' di lock ottimistico in questo senso, fornite da SQL Server, ad esempio una colonna di tipo timestamp/rowversion, che viene aggiornata autonomamente dal motore al momento di ogni attivita' di aggiornamento, che ti puo' aiutare in questo senso... questo sarebbe il lock ottimistico piu' vincolante... altre forme di lock possono essere piu' "leggere", nel senso di verificare che solo le colonne modificate siano ancora come al tempo T0, quindi
UPDATE ...
SET col1 = nuovo_val,
col5 = nuovo_val
col10 = nuovo_val
WHERE chiavePrimaria = valChiavePrimaria
AND col1 = vecchio_val
AND col5 = vecchio_val
AND col10 = vecchio_val che come vedi restringono la ricerca di congruita' con T0, mentre l'utilizzo di rowversion e' in questo senso la piu' restrittiva, in quanto indica che tutta la riga debba essere cosi' come al tempo T0
UPDATE ...
SET col1 = nuovo_val,
col5 = nuovo_val
col10 = nuovo_val
WHERE chiavePrimaria = valChiavePrimaria
AND colRowVersion = vecchio_RowVersion
Lavorando con VB.Net e Access, questo controllo me lo faceva in automatico il Dataset e se tentavo di fare una scrittura su un record modificato, mi dava una eccezione e io rileggevo il nuovo record e lo visualizzavo per permettere la nuova variazione.
Mi consigli di fare la stessa cosa?
non mi risulta che il dataset restituisca questo errore in caso di modifica ai dati se non al momento dell'update reale... ci sono impostazioni sulla concorrenza ma al momento non le ricordo e dovrei riguardare il Sheppa, visto che personalmente NON ho mai usato direttamente i metodi di aggiornamento di dataset e datatable, ma ho sempre operato ciclando sulle righe modificate per eseguire stored procedure di insert/update/delete.... questo e' il mio normale modus operandi.
poi ognuno fa le proprie scelte, compatibilmente con lo standard che vuole/deve adottare e come deve risolvere la concorrenza :D
Comunque la maggior parte delle operazioni saranno sempre come lo scenario 1, anche se i record hanno un numero di campi maggiore di quello che ti ho presentato e posso stare tranquillo per le variazioni. Per quelle situazioni dove l'utente visualizza i dati e lascia la postazione per riprenderli dopo mezz'ora devo vedere come gestirli.
anche il caso 1 va tecnicamente gestito, perche' ad esempio il "+1" potrebbe portarti in overflow, sia "fisico" che "logico" (nel senso che i valori validi di co1 sono magari nel range 1 => n <= 100 (e magari anche in "relazione" ad altra colonna della stessa riga o altra entita')...
quindi va comunque gestito
Modificato da Andrea Montanari il 05 agosto 2021 18:28 - dimenticavo....
salutoni romagnoli :)