Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: petrusic - Ottobre 25, 2022, 05:09:54 pm

Titolo: Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Ottobre 25, 2022, 05:09:54 pm
L'utilizzo del metodo DataModule mi ha portato ad una riflessione sulla proprietà "AutoCommit" dell'Object ZConnection:
 Poichè l'inserimento di un nuovo movimento nel DB determina l'inserimento di 4 record in 4 tabelle diverse del DB, potrei optare per eseguire il Commit una sola vola, alla fine di tutti gli inserimenti e tutti senza la manifestazione d'Errore.
Però non ho trovato come dire a Zeos  "tutto bene, fai Commit"

Lo posso fare?
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: DragoRosso - Ottobre 25, 2022, 08:14:25 pm
Una parola sul "commit" e su cosa significa.

@petrusic hai centrato il significato di "commit". Il "commit" è legato ad una serie di operazioni sul database viste come una sola azione solidale.

Perchè normalmente si usa l'"AutoCommit" ? Perchè per effettuare un commit è necessario aprire una operazione chiamata "Transaction" e con l'AutoCommit attivo il componente attiva automaticamente tale operazione.

Tutto ciò che avviene tra l'inizio della Transaction e il Commit viene visto come un unico blocco di operazioni che terminano con la scrittura finale nel DB SOLO ed ESCLUSIVAMENTE SOLO se TUTTE LE operazioni hanno avuto buon fine.

Nel caso contrario (se attivo l'AutoCommit) viene generato un ROLLBACK automatico, ossia il DB viene riportato alle condizioni di inizio Transaction.

Transaction, Commit e Rollback sono concetti che non tutti i DB hanno, oppure per metterli in opera è necessario usare strumenti esterni non SQL.

L'AutoCommit opera in modo automatico su ogni singola operazione (non è possibile definire un gruppo di operazioni da sottoporre a Commit) e generalmente rallenta le operazioni stesse sul DB.

Non conosco a fondo Zeus e non ho mai fatto operazioni di commit manuale con quei componenti, ma è probabile che ci sia un metodo di StartTransaction che dovrai chiamare, e poi semplicemente il Commit. Se fallisce avrai la generazione di un evento di errore e dovrai fare eseguire un RollBack.

Questo in linea di massima, ogni ambiente di sviluppo ha i suoi strumenti ma più o meno le cose dovrebbero funzionare così.

Attenzione che le "transaction" non è detto siano supportate da tutti i motori DB (ci sono state nel recente passato alcune discussioni su questi argomenti).

Lascio gli approfondimenti ai partecipanti della comunità più ferrati su Zeos.

Ciao
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Ottobre 25, 2022, 10:57:40 pm
Non conosco che a malapena ZEOS, in forzo della minima esperienza acquisita fino ad oggi, ma mi immagino che se se avvia, col metodo DataModule, attivando la proprietà AutoCommit , il Copmmiut venga esegeuito alla conclusione del comando singolo comando SELECT.
Pertanto, se la SELECT agisce su una sola tabella del DB, alla sua conclusione il COMMIT viene eseguito immediatamente.
Allora, come posso ripristinare, nella prima tabella,  la situazione precedente se si manifesta un Errore nella SELECT relativa alla seconda SELECT?
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: DragoRosso - Ottobre 25, 2022, 11:10:45 pm
Non conosco che a malapena ZEOS, in forzo della minima esperienza acquisita fino ad oggi, ma mi immagino che se se avvia, col metodo DataModule, attivando la proprietà AutoCommit , il Copmmiut venga esegeuito alla conclusione del comando singolo comando SELECT.
Pertanto, se la SELECT agisce su una sola tabella del DB, alla sua conclusione il COMMIT viene eseguito immediatamente.
Allora, come posso ripristinare, nella prima tabella,  la situazione precedente se si manifesta un Errore nella SELECT relativa alla seconda SELECT?

Con l'AutoCommit sicuramente non lo puoi fare, a meno che l'inserimento (o la modifica o la cancellazione) dei dati su diverse tabelle o diversi record non provenga da un unico comando (ossia una unica query). Ma anche su questo non ho certezze.

Unico modo sono le transaction, ma occorre che il DB le supporti e occorre che tu impari ad usarle.

Ciao
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Ottobre 26, 2022, 04:42:14 pm
Con l'AutoCommit sicuramente non lo puoi fare, a meno che l'inserimento (o la modifica o la cancellazione) dei dati su diverse tabelle o diversi record non provenga da un unico comando (ossia una unica query). Ma anche su questo non ho certezze.

Si, con un unica SELECT potrebbe funzionare. Tutto sta se riesco a costruirla e se, dopo, Zeos accetta il criterio. Provo e mi faccio vivo.
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Ottobre 29, 2022, 12:07:11 pm
Partendo da questa pagina (https://www.sqlitetutorial.net/sqlite-transaction/), dove spiega che tutti i comandi compresi fra un "BEGIN TRANSACTION;" ed un "COMMIT / ROLLBACK;", estremi fra cui la transazione resta aperta, possono essere dati ed eseguiti correttamente, ho cercato di ripetere il concetto  dentro il mio progetto:
Codice: [Seleziona]
 sql:= 'BEGIN TRANSACTION;';
  DataModule1.ZQuery1Transaz.Active:= False;
  DataModule1.ZQuery1Transaz.SQL.Text:= sql;
  DataModule1.ZQuery1.ExecSQL;

  sql:= 'SELECT IdMovvgg FROM movimgg ORDER BY IdMovvgg DESC';
  numId:= DataModule1.EstraiCodIDMax(sql, 'IdMovvgg');
  numId:= numId + 1;
  codId:= IntToStr(numId);
  descrCorr:= Form2.CBdescr.Text;
  DecodeDateTime(Now, aaaa, mm, gg, ore, minuti, secondi, mSecondi);
  dtOggi:= IntToStr(aaaa) + IntToStr(mm) + IntToStr(gg);
  orario:= IntToStr(ore) + IntToStr(minuti) + IntToStr(secondi);

  sql:= 'INSERT INTO movimgg VALUES(';
  sql:= sql + codId + ', ';
  sql:= sql + dataCont + ', ';
  sql:= sql + dtOggi + ', ';      //  data corrente di registrazione del movimento (aaaaMMgg)
  sql:= sql + orario + ', ';     // ora corrente di registrazione del movimento (hhmmss)
  sql:= sql + 'xxx' + ', ';   // Numero progressivo del movimento corrente nella giornata
  sql:= sql + '123456789' + ', ';   // Codice Voce ddi Sottoconto di Cassa
  sql:= sql + descrCorr + ', ';
  sql:= sql + '€, ';
  sql:= sql + 'importo(1,55)' + ', ';
  sql:= sql + 'Famiglia)';                       
. . .
  sql:= 'COMMIT';
  DataModule1.ZQuery1Transaz.Active:= False;
  DataModule1.ZQuery1Transaz.SQL.Text:= sql;
  DataModule1.ZQuery1.ExecSQL;             
Putroppoo la prova non ha funzionato, perchè già all'esecuzione del primo comando (BEGIN TRANSACTION;), ho ricevuto il
messaggio d'errore SQL Query is Empty.

Io non sono in grado di capire se dipenda da un cattivo uso del comando da parte mia o se , piuttosto, il comando non è supportato in ZEOS.

Non credo che il DB SQLite non supporti le TRANSACTIONS: ho provato a fare una verifica eseguendo il comando "BEGIN TRANSACTION;" dentro DB BROWSER for SQLite. Ebbene, il messaggio informativo restituito (Esecuzione completata senza errori.), è di assoluto conforto.
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: DragoRosso - Ottobre 29, 2022, 04:34:15 pm
L'esecuzione di comandi diretti ai motori DB non è sempre supportato da ZEOS (ma anche altri componenti più blasonati hanno lo stesso comportamento).

Innanzi tutto ZEOS supporta le transaction a livello di connessione. Per fare funzionare le transaction devi operare come ti indico (NON USARE la procedura StarTransaction, le transaction sono automatiche):

1) setta la proprietà "AutomCommit" della ZConnetcion1 a FALSE;

2) fai doppio click sull'Evento ONRollBack sempre di ZConnection1, e nell'evento dovrai disattivare (mettere a FALSE) la proprietà "ACTIVE" di TUTTE LE ZTABLE INTERESSATE DALLE TRANSACTION e di seguito le rimetti a TRUE.  In realtè basta eseguire la procedura REFRESH di ogni tabella. Ciò ha l'unico effetto di mantenere allineata la parte grafica e non ha alcun effetto sulla funzionalità del ROLLBACK o del COMMIT.

3) Esegui la procedura COMMIT e ROLLBACK della ZConnection1 a seconda di cosa vuoi fare, vedi i passi successivi.

4) Per rilevare gli errori devi gestire gli eventi ON..ERROR della ZQUERY1 (o della query interessata). Potrebbe bastarti anche solo l'evento ONPOSTERROR, devi provare.

5) Se rilevi un errore esegui il ROLLBACK come da punto (3). Non importa quante ZQUERY esegui, fino a che non dai un COMMIT tutte le istruzioni che esegui sono sotto Transaction.

6) Se tutte le tue ZQUERY non hanno dato errore allora esegui un COMMIT come da punto (3). Ovviamente nel ciclo ti consiglio di fermarti alla prima ZQUERY con errore e non proseguire con ulteriore ZQUERY legate logicamente.

P.S.: Ovviamente puoi eseguire il ROLLBACK anche in caso non ci siano errori, ad esempio perchè l'utente ha dato un "ANNULLA". Questo sempre prima di una COMMIT.

Spero sia tutto chiaro.

Ciao
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: SB - Ottobre 30, 2022, 06:34:21 pm
Scusate se intervengo. Avevo letto i post ma credevo di aver capito male. Adesso con un esempio di codice credo di aver capito meglio.
Invece di aiutarti a fare quello che vuoi fare, provo a farti cambiare prospettiva.

1) le SELECT sono operazioni di lettura quindi non c'è assolutamente bisogno di includerle in transazioni (o almeno non mi viene in mente niente che lo richieda)
2) ogni istruzione SQL è atomica, in altre parole è gestita come una mini transazione
3) al giorno d'oggi i sistemi sono altamente affidabili e salvo una gestione cialtronesca è difficile che si verifichino errori di origine esterna al programma
4) le transazioni sono isolate e quindi non vedi effetti fino al commit con conseguenti problemi nel caso di accessi multipli
5) ... ci sarà qualcos'altro ma al momento non mi viene in mente...

Detto questo, non vedo l'utilità delle transazioni nel codice che hai postato
Se proprio devi fare 4 INSERT assieme e gli effetti di una interruzione possono causare seri problemi che non hai modo di gestire "manualmente", racchiudi solo queste INSERT nella transazione, assicurandoti di averle preparate PRIMA di entrare nella transazione perchè questa deve durare il meno possibile

Consiglio comunque di valutare se effettivamente qualcosa può andare storto e soprattutto perchè può andare storto. Magari modificando un po' la gestione dei dati ti eviti tante complicazioni inutili.
Ad esempio il codice che hai postato non va bene, è inefficiente e può causare problemi nella multiutenza col rischio di avere identificatori duplicati.
Ci sono altri sistemi per gestire un contatore incrementale. Ad esempio ci sono i campi autoincrementanti, o al limite puoi fare una tabella di contatori dove mettere tutti i contatori che ti servono
Inoltre l'esecuzione di una query restituisce il numero di record interessati ed eventualmente genera un errore che puoi intercettare semplicemente, ad esempio tramite un codice di errore o con un try catch se solleva una eccezione (dipende da cosa usi)

Ultimo consiglio, mai costruire il testo del comando SQL, ma piuttosto usa i parametri



Codice: [Seleziona]
 sql:= 'BEGIN TRANSACTION;';
  DataModule1.ZQuery1Transaz.Active:= False;
  DataModule1.ZQuery1Transaz.SQL.Text:= sql;
  DataModule1.ZQuery1.ExecSQL;

  sql:= 'SELECT IdMovvgg FROM movimgg ORDER BY IdMovvgg DESC';
  numId:= DataModule1.EstraiCodIDMax(sql, 'IdMovvgg');
  numId:= numId + 1;
  codId:= IntToStr(numId);
  descrCorr:= Form2.CBdescr.Text;
  DecodeDateTime(Now, aaaa, mm, gg, ore, minuti, secondi, mSecondi);
  dtOggi:= IntToStr(aaaa) + IntToStr(mm) + IntToStr(gg);
  orario:= IntToStr(ore) + IntToStr(minuti) + IntToStr(secondi);

  sql:= 'INSERT INTO movimgg VALUES(';
  sql:= sql + codId + ', ';
  sql:= sql + dataCont + ', ';
  sql:= sql + dtOggi + ', ';      //  data corrente di registrazione del movimento (aaaaMMgg)
  sql:= sql + orario + ', ';     // ora corrente di registrazione del movimento (hhmmss)
  sql:= sql + 'xxx' + ', ';   // Numero progressivo del movimento corrente nella giornata
  sql:= sql + '123456789' + ', ';   // Codice Voce ddi Sottoconto di Cassa
  sql:= sql + descrCorr + ', ';
  sql:= sql + '€, ';
  sql:= sql + 'importo(1,55)' + ', ';
  sql:= sql + 'Famiglia)';                       
. . .
  sql:= 'COMMIT';
  DataModule1.ZQuery1Transaz.Active:= False;
  DataModule1.ZQuery1Transaz.SQL.Text:= sql;
  DataModule1.ZQuery1.ExecSQL;             

Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: SB - Ottobre 30, 2022, 06:41:13 pm
Dimenticavo... in una INSERT indicare SEMPRE i nomi dei campi a cui ti riferisci. Eviti un bel po' di problemi...
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: DragoRosso - Ottobre 30, 2022, 07:50:20 pm
@SB

Ciao, hai ragione da vendere, però posso questa volta dirti che @petrusic sulle transaction potrebbe avere ragione e questo indipendentemente dalla bontà del codice sviluppato.

Le problematiche di inserzione, ma soprattutto quelle di eventuali DELETE sono sempre in agguato. Se costruisci un DB con chiavi esterne (foreign keys), campi "legati" tipo master / details, o altri costrutti le operazioni di modifica sono sempre a rischio.

Inoltre l'uso delle transaction, anche se di fatto non sono pienamente supportate da tutti i DB e soprattutto dai componenti di sviluppo sono una tecnica che secondo me potrebbero dare una qualità superiore ai prodotti.

Oh chiaramente fermo restando gli altri punti che giustamente tu hai sottolineato.

Nei progetti che ho sviluppato io non ho mai usato la transaction (eccetto casi rari), ma ho condito il codice con tanti di quei controlli per evitare danni che forse usando le transaction avrei sviluppato sicuramente un 30% di meno di linee di sorgente.

Ciao ciao.
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Novembre 16, 2022, 04:44:23 pm
@DragoRosso, @SB

Innanzitutto Vi chiedo scusa per il ritardo con cui rispondo ai vostri post di suggerimenti. Purtroppo ho dovuto rivedere una procedura di compilazione e gestione dati interni a due CombBox, strettamente legate l'una all'altra, e ciò mi è costato tanto tempo. Ora che ho superato dette problematiche, posso riprendere l'argomento "Transaction".

Dal suggerimento ricevuto da
Per fare funzionare le transaction devi operare come ti indico (NON USARE la procedura StarTransaction, le transaction sono automatiche):

1) setta la proprietà "AutomCommit" della ZConnetcion1 a FALSE;

2) fai doppio click sull'Evento ONRollBack sempre di ZConnection1, e nell'evento dovrai disattivare (mettere a FALSE) la proprietà "ACTIVE" di TUTTE LE ZTABLE INTERESSATE DALLE TRANSACTION e di seguito le rimetti a TRUE.  In realtè basta eseguire la procedura REFRESH di ogni tabella. Ciò ha l'unico effetto di mantenere allineata la parte grafica e non ha alcun effetto sulla funzionalità del ROLLBACK o del COMMIT.
. . .
Non ho riportato tutto il post per allungare oltre il dovuto la mia risposta.

L'unica operazione che ho saputo eseguire agevolmente è stata la 1 dell'elenco.

sulla 2a, riguardante il refresh, non ho capito e non ho trovato come eseguire la procedura refresh.

A parte ciò rimane sempre il mio problema iniziale: come passare il comando "BEGIN TRANSACTION" a Sqlite attraverso ZEOS .

Mi dispiace non essere potuto andare avanti, ma ormai conoscete i miei limiti. :-[


Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: DragoRosso - Novembre 16, 2022, 05:55:35 pm
A parte ciò rimane sempre il mio problema iniziale: come passare il comando "BEGIN TRANSACTION" a Sqlite attraverso ZEOS .
.....
Innanzi tutto ZEOS supporta le transaction a livello di connessione. Per fare funzionare le transaction devi operare come ti indico (NON USARE la procedura StarTransaction, le transaction sono automatiche):

Mi pare di avertelo scritto. Se setti l'autocommit a false, la transaction parte automaticamente al primo comando (ad esempio query) e termina o con il COMMIT o con il ROLLBACK. CHE DEVONO ESSERE ESPLICITI A CODICE.
Non servono ne "BEGIN TRANSACTION" ne "StartTransaction". ZEOS supporta (come quasi tutti i componenti simili) 1 transazione sola per connessione.

2) fai doppio click sull'Evento ONRollBack sempre di ZConnection1, e nell'evento dovrai disattivare (mettere a FALSE) la proprietà "ACTIVE" di TUTTE LE ZTABLE INTERESSATE DALLE TRANSACTION e di seguito le rimetti a TRUE.  In realtè basta eseguire la procedura REFRESH di ogni tabella. Ciò ha l'unico effetto di mantenere allineata la parte grafica e non ha alcun effetto sulla funzionalità del ROLLBACK o del COMMIT.
sulla 2a, riguardante il refresh, non ho capito e non ho trovato come eseguire la procedura refresh.

Codice: [Seleziona]
procedure ZConnection1Rollback(Sender: TObject); //// <-------- Evento di RollBack della ZConnection
begin
  ZTable1.Refresh;
end;

P.S.: TRA LA PRIMA QUERY ed il COMMIT o il ROLLBACK posso esserci quante altre QUERY o altre operazioni sul DB. Tutte appartengono alla transaction che dovrà essere chiusa come indicato.
Dopo la COMMIT o il ROLLBACK, riparte il ciclo quindi alla prima Query o altro parte una nuova transaction.

Ciao
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: DragoRosso - Novembre 16, 2022, 06:12:20 pm
Scusate se intervengo. Avevo letto i post ma credevo di aver capito male. Adesso con un esempio di codice credo di aver capito meglio.
Invece di aiutarti a fare quello che vuoi fare, provo a farti cambiare prospettiva.

1) le SELECT sono operazioni di lettura quindi non c'è assolutamente bisogno di includerle in transazioni (o almeno non mi viene in mente niente che lo richieda)
2) ogni istruzione SQL è atomica, in altre parole è gestita come una mini transazione
3) al giorno d'oggi i sistemi sono altamente affidabili e salvo una gestione cialtronesca è difficile che si verifichino errori di origine esterna al programma
4) le transazioni sono isolate e quindi non vedi effetti fino al commit con conseguenti problemi nel caso di accessi multipli
5) ... ci sarà qualcos'altro ma al momento non mi viene in mente...

1) In molti DB (ad esempio uno per tutti FireBird) una transazione parte sin dalla attivazione della connessione, SELECT inclusa. Bisogna tenere presente che ci sono specifiche funzioni, proprie di ciascun DB che possono scatenare azioni anche solo per una SELECT.
2) (*) Vero se non gestisci le transaction.
3) Condivido parzialmente, ma in ambiente multiutente e in rete i problemi sono in agguato e all'ordine del giorno.
4) Il DB và costruito bene, e non ci devono essere interferenze "volute" tra azioni multiutente. Quindi qualunque azione fà un utente è isolata e la transaction per definizione pure, Il rollback o il commit non devono influire sul risultato finale (azioni di altri utenti). Ovvio che devono essere messi in gioco anche sistemi di controllo minimali (ad esempio evitare che due utenti vadano in modifica delle stesso "record" della stessa tabella in contemporanea).
5) Il mondo dei DB è vario ed eventuale. Si potrebbe aprire un forum con tanto di scuola di pensiero su questo argomento.

(*) P.S.: aggiungo che nella singola istruzione SQL il DB deve rimanere coerente al termine della stessa.
Invece la coerenza se vengono usate le transaction è al COMMIT. Non su tutti i db è vero però ciò.

Ciao
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: SB - Novembre 16, 2022, 07:52:33 pm
Non dubito che ci sia qualche pazzoide che riesce a fare le cose più malsane ma non mi sembra il caso di soffermarci su questi casi.
Direi di restare su operazioni "pulite". Anche perchè si scrivono montagne di libri su questi argomenti, e pensare di spiegare tutto in poche righe di messaggio è assurdo.

Petrusic, dal codice postato, mi pare che voglia semplicemente un contatore per identificare i record inseriti
Mi lascia molto perplesso che si voglia a tutti i costi usare le transazioni per questa operazione

Però... fate vobis





Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Novembre 16, 2022, 10:35:14 pm
Petrusic, dal codice postato, mi pare che voglia semplicemente un contatore per identificare i record inseriti
Mi lascia molto perplesso che si voglia a tutti i costi usare le transazioni per questa operazione

Però... fate vobis
Non, non devo contare i record inseriti. Devo proprio eseguire inserimenti di record in tabelle (variabili da 1 a 4) e devo aggiornare alcuni campi di record in almeno 1 tabella.
Premesso che il mio programma non è destinato a multiutenza, visto che lo utilizzo solamente io, vorrei proteggermi, in ogni caso, da rischi di possibili errori durante le operazioni di inserimento e di aggiornamento. Perciò ho sempre pensato di considerare tutto il blocco degli inserimenti e degli aggiornamenti come unico insieme, da confermare alla fine dell'intero trattamento o da annullare, in caso di manifestazione di un Errore qualsiasi, all'interno del suddetto blocco di operazioni.

Tu dici che è esagerato ricorrere alle transazioni, ma se sfrutto la proprietà AUTOCOMIT di ZEOS, ciascun inserimento e ciascun aggiornamento sarà seguito dal commit automatico. Bene, in caso di Errore, come posso ripristinare il contenuto delle tabelle interessate precedente l'ultimo blocco di operazioni finito male?

Io credo che la funzione RollBack sia la più idonea, altrimenti dovrei pensare ad altre operazioni correttive, aggiungendo altri di rischi di manifestazioni di Errori.
Però se il mio ragionamento è sbagliato, sono pronto a cambiare metodo, ma dopo avere capito quale migliore metodo mettere in atto.
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: SB - Novembre 17, 2022, 07:38:37 am
Non ho mai detto che le transazioni sono inutili, vedi il mio intervento.
Però da quel che capisco delle tue esigenze mi sembra che ti stai facendo troppi problemi.
Di ogni soluzione si dovrebbero soppesare costi e benefici e non fissarsi con la prima soluzione che passa per la testa.
Vogliamo una gestione da manuale? Allora proteggiamo tutte le operazioni. Ne vale la pena? No, e in alcuni casi (tipo quello che vuoi fare tu con i contatori) può essere addirittura sbagliato per i motivi che ti ho scritto
Nel tuo caso sei addirittura in monoutenza, con un programma fatto da te e usato da te.
Cosa valuti che possa andare storto? Che salti la corrente e si spenga improvvisamente il computer? Forse avresti ben altri problemi che il salvataggio dei record. Metti un UPS, che magari ti salva da molte altre situazioni
Anche perchè tipicamente succede che proteggi tutto con transazioni e poi ti salta il disco fisso e non hai nemmeno il backup...
Tratti informazioni così importanti e complesse che se fallisce un inserimento succede qualcosa di grave? Forse è meglio rivolgersi a un professionista invece di farsi un programma fatto in casa... In fondo usare le transazioni non è una garanzia che il programma è fatto bene e non ci sono altri tipi di problemi.
Insomma, spero sia chiaro il senso del discorso.
C'è chi cerca di farti fare quello che tu dici di voler fare, io ti dico di ripensare a quello che stai facendo. Poi solo tu sai quali sono le tue reali esigenze.


Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Novembre 18, 2022, 10:19:57 pm
Cosa valuti che possa andare storto? Che salti la corrente e si spenga improvvisamente il computer? Forse avresti ben altri problemi che il salvataggio dei record. Metti un UPS, che magari ti salva da molte altre situazioni
Anche perchè tipicamente succede che proteggi tutto con transazioni e poi ti salta il disco fisso e non hai nemmeno il backup...
Tratti informazioni così importanti e complesse che se fallisce un inserimento succede qualcosa di grave? Forse è meglio rivolgersi a un professionista invece di farsi un programma fatto in casa...
Un professionista?
qui potresti capire (http://www.lazaruspascal.it/index.php?topic=2262.msg14014#msg14014)
 :-X
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Novembre 21, 2022, 06:00:48 pm
Mi pare di avertelo scritto. Se setti l'autocommit a false, la transaction parte automaticamente al primo comando (ad esempio query) e termina o con il COMMIT o con il ROLLBACK. CHE DEVONO ESSERE ESPLICITI A CODICE.
Non servono ne "BEGIN TRANSACTION" ne "StartTransaction". ZEOS supporta (come quasi tutti i componenti simili) 1 transazione sola per connessione.
Ho capito: L'avvio delle Transaction è automatico.
Non riesco però a chiudere la transazione col COMMIT esplicito. Ecco le istruzioni di prova per l'inserimento record:
Codice: [Seleziona]
// Preparo string per l'INSERT nella Tab. movimgg
 sqlInsMovimg:= 'INSERT INTO movimgg VALUES(';
  sqlInsMovimg:= sqlInsMovimg + codIdMovimGG + ', ';
  sqlInsMovimg:= sqlInsMovimg + dataCont + ', ';
  sqlInsMovimg:= sqlInsMovimg + dtOggi + ', ';   
  sqlInsMovimg:= sqlInsMovimg + orario + ', ';   
  sqlInsMovimg:= sqlInsMovimg + IntToStr(nuProMovG) + ', ';
  sqlInsMovimg:= sqlInsMovimg + tbCollegListCBVoxSotCti[ixCbSotCtoSel, 1] + ', ';
  sqlInsMovimg:= sqlInsMovimg + Form2.CBdescr.Text + ', ';
  sqlInsMovimg:= sqlInsMovimg + tipoValuta + ', ';
  sqlInsMovimg:= sqlInsMovimg + strImp + ', ';
  sqlInsMovimg:= sqlInsMovimg + Form2.CBbenef.Text; 

// Preparo string per l'INSERT nella Tab. partmovv
 sql:= 'SELECT IdPartGlob FROM partmovv ORDER BY IdPartGlob DESC';
 numId:= DataModule1.EstraiCodIDMax(sql, 'IdPartGlob');
 numId:= numId + 1;
 codIdPartMovv:= IntToStr(numId);
 striMia:= EstrControPart(tbCollegListCBVoxSotCti[ixCbSotCtoSel, 1]);
 tbControPart:= striMia.Split(chr(13));
 sqlInsPartMovv:= 'INSERT INTO partmovv VALUES(';
 sqlInsPartMovv:= sqlInsPartMovv + codIdPartMovv + ', ';     // IdPartGlob
 sqlInsPartMovv:= sqlInsPartMovv + tbControPart[0] + ', ';   // CoVoPartGlob
 sqlInsPartMovv:= sqlInsPartMovv + dataCont + ', ';           // DtCoPartGlob
 sqlInsPartMovv:= sqlInsPartMovv + dtOggi + ', ';            // DtSolPartGlob
 sqlInsPartMovv:= sqlInsPartMovv + orario + ')';             // OraSo

//-------------------- Esguo Blocco di Inserimento di Nuovi record nel "ContabFamdb" --------------------
  DataModule1.ZQuery1Transaz.Active:= False;
  DataModule1.ZQuery1Transaz.SQL.Text:= sqlInsMovimg;   
  DataModule1.ZQuery1.ExecSQL;    //  Insert nel Tab. movimgg
  DataModule1.ZQuery1Transaz.Active:= False;
  DataModule1.ZQuery1Transaz.SQL.Text:= sqlInsPartMovv;
  DataModule1.ZQuery1.ExecSQL;     //  Insert nel Tab. partmovv

// Terminati i comandi INSERT, senza segnalazione d'error4e, tento il COMMIT
  DataModule1.ZQuery1Transaz.Active:= False;
//  DataModule1.ZQuery1Transaz.SQL.Text:= ' COMMIT';    // 1.a  Prova - Errore logico
//  DataModule1.ZQuery1Transaz.SQL.Text:= ' COMMIT TRANSACTION';    // 2.a  Prova - Nessun Errore, ma anche nessun nuoio record
   DataModule1.ZQuery1Transaz.ExecSQL;                                                       
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: DragoRosso - Novembre 23, 2022, 12:39:01 am
La COMMIT deve essere effettuata tramite la TZConnection (ad esempio ZConnection1):

Codice: [Seleziona]
ZConnection1.Commit; //Esegue la Commit manuale
//oppure
ZConnection1.RollBack; //Esegue il RollBack manuale

Questo perchè ZEOS supporta le transazioni solo a livello di "connection" (1 transazione attiva e possibile per connessione).

Ciao
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Novembre 23, 2022, 10:57:05 am
Va bene.
Finalmente ce l'ho fatta.
Ha funzionato tutto. C'erano alcuni errori nella formazione delle stringhe dati per l'inserimento record e anche qualcosina dimenticata nel richiamo delle ZConnection.
[/code]
Penso quindi di essere a buon punto col mia prima modifica dati di un D.B

2) fai doppio click sull'Evento ONRollBack sempre di ZConnection1, e nell'evento dovrai disattivare (mettere a FALSE) la proprietà "ACTIVE" di TUTTE LE ZTABLE INTERESSATE DALLE TRANSACTION e di seguito le rimetti a TRUE.  In realtè basta eseguire la procedura REFRESH di ogni tabella. Ciò ha l'unico effetto di mantenere allineata la parte grafica e non ha alcun effetto sulla funzionalità del ROLLBACK o del COMMIT.

il mio codice di modifica tabelle è:
Codice: [Seleziona]
DataModule1.ZConn1Transaz.Database:= dbCorr;
  DataModule1.ZQuery1Transaz.Active:= False;
  DataModule1.ZQuery1Transaz.SQL.Text:= sqlInsMovimg;
  try
    DataModule1.ZQuery1Transaz.ExecSQL;
  except
    DataModule1.ZQuery1Transaz.SQL.Text:= 'ROLLBACK';
    DataModule1.ZQuery1Transaz.ExecSQL;
    ShowMessage('Errore "'+ E.Message + '" durante l''ExecSQL(' + sqlInsMovimg + ')' + LineEnding + LineEnding + 'Transazione FALLITA - Il programma verrà chiuso' ););
    Halt;
  end;
  if (Length(sqlInsPartMovv) > 0) then
  begin
    DataModule1.ZQuery1Transaz.SQL.Text:= sqlInsPartMovv;
    try
      DataModule1.ZQuery1Transaz.ExecSQL;
    except
      DataModule1.ZQuery1Transaz.SQL.Text:= 'ROLLBACK';
      DataModule1.ZQuery1Transaz.ExecSQL;
      ShowMessage('Errore "'+ E.Message + '" durante l''ExecSQL(' + sqlInsPartMovv + ')' + LineEnding + LineEnding + 'Transazione FALLITA - Il programma verrà chiuso' ););
      Halt;
    end;
  end;
  DataModule1.ZQuery1Transaz.SQL.Text:= 'COMMIT';
  DataModule1.ZQuery1Transaz.ExecSQL;             
Il verificarsi di un'anomalia durante la modifica nel D.B., in base al mio tipo di urilizzo, CREDO CHE SIA alquando impropabile, per cui ho previsto la chiusura brutale del programma, dopo il RollBack. Ritengo pertanto altresì non necessario eseguire un refresh delle tabelle già modificate, solo per  mantenere allineata la parte grafica.

@ DragoRosso
Mi dispiace non poterti ringraziare di persona per tutto l'aiuto di supporto che mi hai voluto apportare, aiuto senza il quale non avrei sicuramente imparato tanti piccoli segreti sull'argomento D.B.  e ZEOSLIB.
Titolo: Re:Commit manuale di ZConnectiopn tramite modulo dati
Inserito da: petrusic - Novembre 23, 2022, 10:58:17 am
La COMMIT deve essere effettuata tramite la TZConnection (ad esempio ZConnection1):

Codice: [Seleziona]
ZConnection1.Commit; //Esegue la Commit manuale
//oppure
ZConnection1.RollBack; //Esegue il RollBack manuale

Questo perchè ZEOS supporta le transazioni solo a livello di "connection" (1 transazione attiva e possibile per connessione).

Ciao

Ho capito. Grazie ancora