AdoNet in modalità disconnessa e multiutenza

sabato 03 dicembre 2005 - 20.37

alextyx Profilo | Expert

Lavorato incessantemente ai fianchi dalla necessità di adeguarsi al 'resto del mondo', sto prendendo in esame la possibilità di utilizzare ADO.Net con tanto di DataAdapter, DataTable, DataSet e compagnia bella, tentando di utilizzarli a regola d'arte, ossia con connessione aperta x il tempo strettamente necessario, lavoro disconnesso e successivo Update dell'origine dati. Per la terza volta, ho ripreso in mano i sacri testi (Balena) e mi sono immerso di nuovo nella decriptazione degli iniziatici misteri legati all'uso degli oggetti poc'anzi citati. Tutto bello, ma nonostante mi si dica da alcune parti che sicuramente la Microsoft ha risolto il problema (però chi me lo dice non sa come e non ha mai fatto un vera applicazione multiutenza!) a me resta qualche perplessità che confido si scioglierà come neve al sole sotto alla luce della conoscenza della quale spero vogliate mettermi a parte. Siccome credo di essere l'unico VBNettista del forum ad avere usato ADO, quasi tutti gli amici che hanno lavorato con qualche database ne sanno di certo più di me su ADO.Net e quindi....eccovi i miei dubbi:
Ho un programmino che, tra le altre, gestisce tre tabelle di un database Access MDB:
TabRegistrazioni, TabNota e TabRiferimenti, con rispettive chiavi primarie IDRegistrazione, IDNota, IDRiferimento (fantasia, vero? ) Le chiavi sono i classici campi contatore incrementale univoco.
La Tabregistrazioni contiene dati delle fatture, la TabNota i dati dei movimenti di banca o cassa (importo, origine, destinazione, ecc...), la TabRiferimenti contiene dati riguardanti quanto di un certo movimento viene assegnato ad una certa fattura. Quindi si avrà in TabNota un movimento dal cliente Pippo, verso la mia Cassa, che sarà associato, grazie alla TabRiferimenti, in tutto o in parte, alla fattura, per esempio, 132/2005. Per ottenere questo nella TabRiferimenti avrò, tra gli altri, un campo importo, un campo IDNota e un campo IDRegistrazione.
Ammettiamo ora che due utenti si connettano al database, formino un loro bel dataset, si disconnettano e comincino a lavorare. Al momento della loro connessione essi hanno trovato: IDNota=100, IDRegistrazione=120, IDRiferimento=150
Entrambi registrano una fattura(ovviamente ognuno avrà per le mani una fattura diversa da quella dell'altro) e nel loro database, disconnesso, viene generata una datarow nuova con IDRegistrazione 121, poi passano una contabile che riferisce di un bonifico e la registrano con lo IDNota 101, infine, visto che il bonifico si riferiva proprio alla fattura appena passata, aggiungono una riga nella TabRiferimenti, che avrà IDRiferimento=151, IDRegistrazione=121, IDNota=101.
Il problema è che i due utenti si trovano questi numeri uguali, che dovrebbero identificare univocamente delle registrazioni, ma che invece si riferiscono a cose completamente diverse.
Al momento della riconnessione e dell'Update dell'origine dati, con che criterio viene risolta la controversia? Sicuramente un automatismo deve esserci, mi si dice, ma non avrò il coraggio di utilizzare ADO.Net in questa forma, finchè non avrò capito come la risolve. Io ho in testa delle ipotesi, ma non mi pare di aver letto che ciò che mi frulla in testa sia effettivamente implementato in ADO.Net, per cui rimango molto perplesso sulla faccenda! Chi può, mi aiuti. Grazie!

Brainkiller Profilo | Guru

>Al momento della riconnessione e dell'Update dell'origine dati, con che criterio viene risolta la controversia?

Si tratta di vedere se scegliere la concorrenza optimistic o pessimistic.
Durante l'update ti viene scatenata un'eccezione a quel punto devi decidere tu cosa fare. Se accettare o meno le nuove variazioni.

> Sicuramente un automatismo deve esserci

Non è proprio un automatismo ma il Framework ti mette a disposizione tutti gli strumenti necessari.

> mi si dice, ma non avrò il coraggio di utilizzare ADO.Net in questa forma,
> finchè non avrò capito come la risolve.

In effetti avevo fatto lo stesso ragionamento anche io però poi ho studiato un po' ed ho scoperto come funziona il tutto e come si applica. Nel mio processo di studio ho scoperto un interessante documento che ti può avviare sulla giusta strada. Lo trovi nel Framework SDK sotto la voce "optimistic concurrency". Trovi un'ottima guida che darà soluzione ai dubbi che hai in questo momento.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconOptimisticConcurrency.asp

Prova a dargli una lettura e poi ci confrontiamo ancora.
Ciao

David De Giacomi
Microsoft MVP
http://blogs.dotnethell.it/david/

alextyx Profilo | Expert

Grazie della risposta. Sicuramente i mezzi per risolvere i problemi ci sono. Diventano tanto più complessi quanto più si spinge il ragionamento al limite. Pensa allo scenario che ho descritto e immergilo in una situazione di ore di lavoro 'disconnesso' con riconnessione e successivo update di centinaia di registrazioni. Volendo si trova il sistema di far funzionare tutto, ma va valutato il rapporto costi/benefici. La cosa più sensata mi sembra sia quella di procedere alla riconnessione momentanea x ogni record editato, aggiunto o cancellato. Certamente si lavora anche con locking ottimistici, anzi, forse quasi mai c'è bisogno del pessimistico, ma credo che sia il massimo che si può concedere. E comunque sarebbe stato meglio se ADO.net avesse offerto supporto al locking pessimistico, casomai dovesse servire. Il fatto di lavorare quasi esclusivamente con cursori lato client, su un database 'replicato', richiede maggiore attenzione di quanta non fosse necessaria con ADO. L'idea che mi sono fatto è che, pur non potendo prescindere da ADO.Net, perchè Microsoft lo sta praticamente imponendo, per applicazioni di un certo tipo e fino ad una certa 'scala', si lavora più sereni con ADO e con cursori lato server. Diciamo che sarei curioso di sapere chi usa ADO.Net in applicazioni multiutenza, senza connettersi ad ogni pie' sospinto. Nel libro di Balena, sono descritte varie strategie x affrontare eventualità del genere, incluso il racchiudere tutto in una transazione ed eventualmente procedere al rollback di tutti gli aggiornamenti, in caso di errore inaccettabile. Onestamente mi pare una difesa d'ufficio di una tecnologia pensata sicuramente x internet e che, spinta a quel livello, può andar bene x certe forme di e-commerce, ma mi pare poco proponibile in altri ambiti. Detto questo...sotto a lavorare con ADO.Net, sapendo a cosa si va incontro, comunque! :)

Cteniza Profilo | Guru

Ribadisco quanto ti ho già detto in altro forum.
Per me la soluzione ottimale NON è la gestione disconnessa e NEANCHE il lock pessimistico.
Per ogni situazione è necessario disegnare una strategia diversa.
Probabilmente suddividere i dati per tipologia di repository aiuta un pò a decidere, alcuni esempi:
- tabella clienti -> disconnessa
- tabella prodotti -> disconnessa
- inserimento movimenti, alla fine della gestione utente immediata trasmissione della variazione intervenuta
- gestione documento, alla fine della gestione di testata / dettagli (quando l'operatore fa una azione che indica che vuole "cambiare documento") parte l'inserimento / aggiornamento del documento
- stampa documenti, numerazione del documento affidata ad una stored procedure sotto transazione.
In ogni caso gestione di un campo timestamp per testare se il record che si sta variando è proprio quello preso durante la lettura dei dati del database.


alextyx Profilo | Expert

Ciao Cteniza, ben ritrovato anche qui. Come vedi, avevo fatto 'metastasi' con questa faccenda! :)
E infatti...anche secondo me si deve attrezzare la logica in maniera elastica. Non penso affatto che lavorare con ADO.Net sia impossibile, ovviamente. Come sai, l'ho sempre guardato con una certa apprensione, perchè mi ha dato l'idea di un oggetto creato pensando soprattutto a certi scenari di rete e da 'adattare' in qualche modo a scenari più 'a misura d'uomo', che poi sono quelli della piccola e media impresa italiana. Il lavorare disconnesso ed effettuare una riconnessione, magari a fine giornata, mi sembra francamente applicabile solo a certi tipi di lavori e soprattutto laddove le velocità delle connessioni o l'esagerato numero di utenti, costituiscono veramente una barriera. Quanto al timestamp, in certi casi può essere utile, ma il sistema di ricontrollare il valore di ogni campo, senza campi timestamp, ha anche il suo vantaggio: se un valore è stato cambiato e poi ripristinato come in origine, il campo timestamp, se non sbaglio, ti risulta comunque variato e 'scatta l'avviso', i campi non timestamp risultano coerenti con le letture primitive e l'eventuale aggiornamento va a buon fine, come nella stragrande maggioranza dei casi sarebbe nelle intenzioni dell'utente. Comunque, anche se ora non mi viene in mente dove potrebbe servirmi, non escludo che in futuro l'uso del timestamp non debba entrare anche in qualche mia applicazione. Se dovessi convertirmi a MSDE, casomai, ti scoccerò un po' x avere qualche dritta. Io l'ho già usato, ma non avevo implementato niente da codice per la manutenzione/amministrazione. Grazie ancora delle risposte a entrambi.

Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5