Newsgroup: it.comp.lang.delphi
Titolo: Adoquery1 in memoria.

Salve,
avrei bisogno di lasciare in memoria le modifiche effettuate ad una adoquery, 
mi spiego:
Adoquery in locktype : ltBatchOptimistic
1. Select su tabella dipendenti in access visualizzo adoquery1 in dbgrid1 modifico in dbgrid1. Ma non salvo
2. Select su tabella fornitori in access visualizzo adoquery1 poi in dbgrid1 l'utente modifica. Ma non salvo
3. Select su tabella clienti di access visualizzo con adoquery1 poi sempre in dbgrid1 l'utente modifica. 
4. Richiamo la prima select su tabella dipendenti e vorrei trovarci le modifiche effettuate in precedenza quando poi avrò controllato tutto chiedo di salvare nel database le modifiche effettuate su tutte le tabelle. 
Si può fare sta cosa o devo chiedere di confermare le modifiche ogni volta? Non c'è un metodo per creare un mirror al database e poi sincronizzare i dati? 

Quando dici "Non salvo", di CHI stai parlando?
Dell'utente finale o di chi altro?
A prescindere, trovo questa cosa molto macchinosa e con troppi spazi per commettere errori.
 
Facciamo un passo indietro: quale e' il problema che speri di risolvere in questo modo?
 
A.

Si ovviamente l'utente. 
Il problema da risolvere è: usare la stessa adoquery più volte modificarla più volte e salvare una sola volta. 
In pratica vorrei visualizzare dipendenti e fare modifiche, fornitori e fare modifiche clienti e fare modifiche... Alla fine quando sto per chiudere il programma "Vuoi salvare ?" si no annulla. Molto meno macchinoso di avere dipendenti vuoi salvare le modifiche a dipendenti?
fornitori vuoi salvare le modifiche a fornitori?
clienti vuoi salvare le modifiche a clienti?
dipendenti l'utente sempre rimodifica poi si sposta su fornitori e per non perdere le modifiche devo chiedergli di salvare. 
Siccome che devo passare tra più tabelle l'utente si rompe di vedersi comparire tante volte il messaggio vuoi salvare?
Una soluzione ci sarebbe ma non mi piace. Dovrei creare una tabella.mdb identica esempio clienti -> clientimirror.mdb quest'ultima prende i record interessati sa clienti e li modifichi come vuoi poi se salvi sincronizzi con la principale. 
In pratica non lavorare sui dati reali ma su una copia dei dati per poi rimettere tutto a posto. 
Mi direte: "ma già una query funziona così". Ed invece no se io chiamo una query questa mantiene in memoria le modifiche ma se ne chiamo un'altra (SULLO STESSO ADOQUERY) senza aver confermato le modifiche queste ultime andranno perse. 

 clienti vuoi salvare le modifiche a clienti?
 
Se l'utente � nelle angrafiche clienti, e modifica un cliente, dopo la
richiesta di conferma e il suo ok, il software salva... punto e basta.
 
Non devono esserci strategie "di accumulo" dei salvataggi: quando
l'utente vuole abbandonare una anagrafica modificata, si assume la
responsabilit� di decidere se perdere o salvare la singola modifica.
 
E' inutile e confusionario tenere la traccia di tutto quello che � stato
modificato, soprattutto se riguarda anagrafiche differenti: non si
ricorda nessuno se ha modificato prima un fornitore, poi un aritcolo,
poi un dipendente... � del tutto inutile.
 
Ad ogni singola modifica, devi chiedere di salvare: � cos� che va in
ogni parte del mondo, tutti i giorni.
 
-- 
morde
Android
QT 4.7
Delphi (5,6,7.. expired)
Firebird Database
 

 a dipendenti?
 
Ognuno ha le sue idee. Io vedo questa cosa molto piu' macchinosa.
 
In primis, l'utente deve RICORDARE cosa ha modificato: non lo faranno mai.
E poi sarai TU a dover capire, a fronte degli inevitabili casini, cosa ha fatto l'utente.
Ancora, questo modo di lavoro non e' standard e sembra un tentativo di vincere l'inerzia sociale del "tutti i sw lavorano in un certo modo, se pur sbagliato".
Tentativi del genere FALLISCONO.
 
Infine, riguardo la sincronizzazione mi piacerebbe che postassi un elenco sintetico delle cose da tener presente e di come avresti intenzione di risolverle.
 
 
A.


 [...]
 
Io userei il componente *TClientDataSet* collegandolo alla *TADOQuery* tramite il *TDataSetProvider*: ti fornisce una cache in cui scaricare i dati e su cui lavorare tramite la tua griglia; le modifiche vengono salvate in memoria e solo nel momento in cui chiami il metodo ApplyUpdates() sul componente queste vengono "trasferite" al database.
 
La spiegazione è ovviamente semplicistica, ma puoi trovare ovunque parecchio materiale, documentazioni ed esempi per capire se è applicabile al tuo caso.
 
Ciao,
  Marco.
 
-- 
MARCO BREVEGLIERI (Software and Web Developer)
#Home: 
http://bit.ly/marcobreveglieri
 
#Blog: 
http://bit.ly/compilaquindiva
 

Una tabella è un insieme di record memorizzati sul disco fisso, una query è una parte di quella tabella. Se modifico in una query le modifiche sono direttamente   salvate sul disco fisso. Capite fin quì nulla da capire no? La adoquery come pure la TTquery ti da la possibilità di modificare i dati in memoria e poi salvarli in un unica sessione, in pratica puoi fare diverse modifiche queste restano in memoria ed alla fine queste vengono applicate. 
Ora pensavo ci fosse un metodo per creare un cache del database sulla quale chiamare delle query, modificare, inserire record ed alla fine questo sincronizza il tutto con le tabelle del disco rigido, ma a sentirvi non esiste sta cosa.
 
Ad esempio nel mio caso è creare un organizer settimanale dove scegli cosa fare lunedi martedi mercoledi poi magari rivedi lunedì e poi velocemente giovedì così magari fai delle modifiche ma non vuoi che ti esce quel messaggio rompi... che ti chiede di salvare. 
Quando mi sono organizzato tutta la settimana salvo una sola volta. 
Il mondo funziona anche snellendo e semplificando la vita ad un utente che si stufa vedersi apparire sempre il messaggio: "Il piano giornaliero di lunedì è stato modificato vuoi salvare?" "Il piano giornaliero di martedì è stato modificato vuoi salvare?" "Il piano giornaliero di mercoledì è stato modificato vuoi salvare?" "Il piano giornaliero di lunedì è stato modificato vuoi salvare?" "Il piano giornaliero di giovedì è stato modificato vuoi salvare?" Poi pensa di rimodificare  il piano di lunedì e di nuovo martedì e compare: "Il piano giornaliero di lunedì è stato modificato vuoi salvare?". 
Il fattaccio è che devo usare la stessa adoquery e la stessa dbgrid.
Proverò con TDataSetProvider. 
 

 Il mondo funziona anche snellendo e semplificando la vita ad un utente che si stufa vedersi apparire sempre il messaggio: "Il piano giornaliero di lunedì è stato modificato vuoi salvare?" "Il piano giornaliero di martedì è stato modificato vuoi salvare?" "Il piano giornaliero di mercoledì è stato modificato vuoi salvare?" "Il piano giornaliero di lunedì è stato modificato vuoi salvare?" "Il piano giornaliero di giovedì è stato modificato vuoi salvare?" Poi pensa di rimodificare  il piano di lunedì e di nuovo martedì e compare: "Il piano giornaliero di lunedì è stato modificato vuoi salvare?". [...]
 
In quel caso, basta consentire di disattivare il warning, o rimuovere la richiesta se non ha senso o non ci sono validi motivi di sicurezza per proporla.
 
Se l'interfaccia utente e il comportamento del programma è errato o inefficace, non è detto che questo abbia a che vedere con le dinamiche di accesso ai dati o l'impossibilità di fare query in memoria.


 Il fattaccio è che devo usare la stessa adoquery e la stessa dbgrid.
 
Se è legata ad un piano settimanale perché non usare sette adoquery 
diverse, una per ogni giorno della settimana?
 
-- 
@WarpTen10

7 query? Per 7 giorni? L'organizer è solo un minimo esempio questa tecnica in alcuni casi mi porterebbe ad usare 50 componenti adoquery non proprio una passeggiata.
Faccio un altro esempio:
 
Un solo adoquery con locktype = ltBatchOptimistic una sola dbgrid
Select * from giorni (tabella in access) where giorno = 'Lunedi';
  risultato query
vai a scuola (old dati) marina la scuola (new dati)
vai a calcio
vai in palestra
 
Quì deve starci un salva ma troppo palloso per l'utente.
 
Sempre sulla stessa adoquery con locktype= ltBatchOptimistic una sola dbgrid
Select * from giorni (tabella in access) where giorno = 'Martedi';
risultato query
vai a pescare
vai in riunione
 
Quì deve starci un salva ma troppo palloso per l'utente.
 
Sempre sulla stessa adoquery con locktype= ltBatchOptimistic una sola dbgrid
Select * from giorni (tabella in access) where giorno = 'Martedi';
risultato query
vai a scuola (old dati) ma quì avevo modificato ops errore 
vai a calcio
vai in palestra
 
Quì deve starci un salva ma troppo palloso per l'utente.
 
N.B. se locktype = ltOptimistic funziona tutto ok perchè in ltoptimistic i cambiamenti sono definitivi. Quindi se l'utente sbaglia so c----. 
 
Cosa fa locktype= ltOptimistic lavora direttamente sulla tabella tu modifichi inserisci e se non sei convinto fregati.
Se richiami un'altra query i dati sul disco rigido ti ritornano aggiornati.
 
Cosa fa locktype= ltBatchOptimistic fa una copia dei dati in memoria tu li modifichi li aggiusti inserisci record e se proprio sei convinto salvi.
Se richiami un'altra query i dati in memoria sono cancellati.
Vorrei quindi che i dati in memoria non vengano persi.
 
Mi soluzione 
lasciare i locktype = ltOptimistic e:
creare un'altra tabella giorni in access. Due tabelle identiche giorni e giorni1
giorni i dati e giorni1 vuota.
Copio i dati da giorni a giorni1 faccio tutte le modifiche inserimenti e varie su giorni1 query update e poi a fine sessione aggiorno la tabella giorni svuotando la tabella giorni1. Cioè lavorare su una copia dei dati controllare i dati aggiornare i dati inserire i dati e se proprio si è convinti quando e solo voglio io salvo i dati.
 
In questo modo io chiamo con un solo adoquery ed un solo dbgrid tutte le query che voglio e queste mi risultano sempre aggiornate alla sessione. E salvo una sola volta. 
 
Credevo esistesse un componente per fare tutto ciò o quanto meno un metodo più pulito.
 
 
 

 Credevo esistesse un componente per fare tutto ciò o quanto meno un metodo più pulito.
 
Quale parte della parola *TClientDataSet* non è chiara? :)


 Credevo esistesse un componente per fare tutto ciň o quanto meno un metodo piů pulito.
Hai letto il consiglio di Marco sul TCLiendtDataset?
 
Mi sa che continui a guardare il dito invece che la luna.. tu continui a
ragionare nella tua logica ignorando i consigli funzionali come il mio e
tecnici come quello di Marco o di Warp.


Il tuo problema non e' avere una sola query ma:
 
avere una lista di modificabile di elementi filtrata in base al giorno.
 
 
Il resto non e' "problema" ma "pezzi di soluzione".
Stai dando x scontato che la tua lista debba essere un tdataset.
Non potrebbe essere invece una collection di elementi "impegno del giorno" che include data, ora etc?
 
cosi su 2 natiche:
 
1) 1 classe "impegno del giorno": data, ora, testo etc...
2) 1 classe collection di questi elementi
3) 1 classe frame che contiene una griglia che mostra sta kaz di collection
4) un form con 1 page control con 7 tab lunedi, martedi etc
5) ognuno dei tab contiene una istanza del frame al punto 3
6) sull'hide di un tab fai il save della collection gestita dal frame conenuto nel tab
7) sullo show di un tab fai una query che popola la collection di elementi gestita dal frame contenuto nel tab
 
Questa soluzione parte del presupposto che non usi componenti gia' pronti per gestire scheduler dipo i devex o altro e che mostri UNA SETTIMANA ALLA VOLTA.
Ovviamente la si puo adatttare eliminando il page control, avendo un solo frame  e sostituendo hide e show dei tab al click un tdatetimepicker..
 
Facendo cosi, "magicamente" tutti i tuoi problemi o presunti tali, SMETTONO DI ESISTERE. O no?
 
 
A.

Mi autocorreggo: il save non si fa sull'hide ma sul "change" del singolo elemento. In questo modo non hai il problema ovvio (ma non per tutti) che se l'utente non cmabia il tab il save non scatterebbe.
 
A.

Tutto ok ci sono riuscito ma come ho fatto a non pensarci prima semplice proprio. Chiamo la query su adoquery1 con locktype=ltBatchoptimistic  cosi "select * from giorni" e basta ottengo una query contenente tutti i giorni. Lunedì Martedi Mercoledi Giovedi ed uso la proprieta adoquery1.filter:='giorno='+giornochevoglio.
La proprietà filter in questo caso è come se eseguisse una query su di una query e la cosa più bella che lavora sulla memoria. Così alla fine dopo aver modificato tutti i giorni posso salvare una sola volta, con un solo adoquery ed un solo dbgrid e un combobox contenente tutti i giorni. Bello vero?

....contento tu....

E certo che sono contento ho risolto un problema che solo per spiegarlo ho impiegato 9 post e la cosa più bella che forse manco avete capito qual'era il mio problema.

 E certo che sono contento ho risolto un problema che solo per spiegarlo ho impiegato 9 post e la cosa più bella che forse manco avete capito qual'era il mio problema.
 
Il problema si era capito a grandi linee, però è ovvio che senza codice specifico o trattandolo a un livello molto astratto, è difficile dare suggerimenti molto circostanziati.
 
La tua soluzione, tra l'altro, pur funzionando nel caso specifico, non è detto che ti salvi da "mal di pancia" in futuro a seconda di come evolverà il tuo software e le sue funzionalità.
 
Comunque sia, come diceva qualcuno, quando sei contento tu e in particolare il tuo cliente, a posto così. :)


Marco ma guarda che nel caso specifico non ho adottato nessuna soluzione di mia crazione, ho usato semplicemente due proprietà del componente adoquery1, è stato chi ha progettato il componente che aveva già previsto questo tipo di problema. 
A volte ci sono quelle proprietà che dici ma a che può servire poi quanto ti trovi nel problema specifico capisci a che serve quella proprietà. Un sacco di volte mi ero chiesto ma sta proprietà filter su adoquery a che serve... serve serve...