Che venga inserita dall'utente, o che venga creata automaticamente, il campo chiave deve essere sempre attribuito al record prima di salvarlo all'interno del ClientDataSet, poiché questo consente al componente di aggiornare tale record dopo averlo inserito, se inesistente, nel database sottostante. Nel caso di campi autoincrementali, il valore va prelevato usando un apposita stored o un apposito strumento, come i "generatori" in FireBird, e attribuito al record prima di salvarlo.Originariamente inviato da Brendon77
in questa applicazione la chiave primaria deve essere inserita manualmente (di solito preferisco crearla autoincrementante ma me l'hanno chiesta così), sorge inevitabile un controllo sulla stessa.
E questo è il primo problema: il ClientDataSet dovrebbe avere ottenuto i record dal database, a cui vai aggiungere nuovi record da salvare successivamente chiamando ApplyUpdates.Originariamente inviato da Brendon77
Naturalmente, nel momento che si cerca di inserire una chiave primaria già presente, il metodo "ApplyUpdate" fallisce, viene lanciata l'eccezione e il record viene però inserito lo stesso, non fisicamente sul Database ma in memoria, siccome il componente CLIENTDATASET opera proprio in memoria.
E' necessario impostare un campo come chiave per evitare che il record venga inserito nel CDS se la chiave è duplicata, senza attendere il momento in cui questo verrà inviato al server.
Non è un comportamento normale, o meglio lo è se il componente CDS non è configurato correttamente.Originariamente inviato da Brendon77
Questo è un comportamento normale.Definisci un indice sul componente CDS usando la proprietà IndexDefs e assegnandogli l'attributo di univocità, oltreché facendolo riferire al campo chiave.
Quell'evento viene generato nel momento in cui il Post di un record nel CDS fallisce.Originariamente inviato da Brendon77
Ho deciso allora di scrivere un evento "OnPostError" del CLIENTDATASET in modo da gestire l'errore (sempre in memoria).
Il problema è dato dal fatto che se non vi è da alcuna parte una condizione che fa fallire l'operazione, l'evento non viene mai generato. Se inserisci un record con chiave duplicata in memoria e non c'è nulla che verifica questa condizione, non si verificherà nemmeno l'errore relativo e quindi l'evento OnPostError, generato quando si verifica un'eccezione, non verrà mai eseguito.
In sostanza, il CDS accetta qualsiasi record di buon grado, almeno fino a quando questi rimangono in memoria.
Questo non è vero. Quando invochi ApplyUpdates, salvi sul DB le modifiche apportate ai record nel CDS (inserimenti, aggiornamenti, cancellazioni): queste modifiche a livello di CDS sono definitive e confermate. Se ApplyUpdates fallisce, tali record rimarranno nel CDS, solo non verrà aggiornata la base dati sottostante (in questo caso, tocca allo sviluppatore prendere provvedimenti per correggere i record).Originariamente inviato da Brendon77
In questo modo, lancio un messaggio di errore (siccome la chiamata al metodo UpplyUpdate fallisce) e con il metodo:
"ClientDataSet1.RevertRecord;"
faccio in modo di tornare alla situazione in memoria prima della chiamata di UpplyUpdate
Se invochi la RevertRecord, non fai altro che annullare le modifiche all'ultimo record nel caso in cui tu non riesca a salvare sul DB tutte le modifiche apportate a quello e ad altri record eventualmente presenti. E' un po' come se io scrivessi una riga di dati e, a causa di un campo non corretto, mi venissero annullate tutte le modifiche apportate, costringendomi a riscrivere tutto di nuovo.
Questo è ciò che già avviene quando la ApplyUpdates fallisce: non è necessario, anzi è errato, invocare RevertRecord.Originariamente inviato da Brendon77
In questo modo, non solo viene avvertito l'utente che un errore è stato generato (in questo caso la chiave primaria duplicata), ma evita di scrivere nel ClientDataset il nuovo record che sarebbe inesatto siccome avrebbe una chiave primaria già utlizzata.
Meglio procedere "per gradi", studiando il funzionamento del database layer e delle sue peculiarità, per approfondire poi il funzionamento dei componenti per l'accesso ai dati e infine mettere assieme le cose. Usando tutto e subito in questo modo, a fronte di problemi, non si sa a chi dare la colpa, anche perché non sono ben chiari meccanismi che riguardano tutte le parti in gioco.Originariamente inviato da Brendon77
Le prove che ho fatto, forse le ho scritte in modo confusionale, sono dettate dal fatto che, dopo averci sbattuto la testa e non riuscendo a capire, mi sono reso conto che l'errore me lo dava Firebird Embedded ma non ne ero sicuro così ho chiesto aiuto (è la prima volta che utilizzo Firebird in generale).
Anche l'applicazione che esegui da Delphi è compilata: è sempre un eseguibile che viene prodotto e lanciato.Originariamente inviato da Brendon77
Per la mia applicazione ho utilizzato la versione "non embedded". Tutte le applicazioni Delphi sono naturalmente compilate, ma come avevo detto, ho copiato tutte le librerie e il file EXE in una cartella esterna per verificare il funzionamento della versione embedded su un altro PC... lo scopo era proprio questo![]()
Meglio risolvere i problemi esistenti prima di passare ad un'altra versione del database server.Originariamente inviato da Brendon77
Far funzionare l'applicazione su un computer su cui non era installato Firebrid e capire come funzionava la versione Embedded.
Non è necessario, anzi io in genere non lo faccio: modifico la proprietà VendorLib del componente TSQLConnection nel modo opportuno, altrimenti non si ha mai la certezza di quale libreria client di database si sta utilizzando.Originariamente inviato da Brendon77
Dalla documentazione di Firebird ho letto che dovevo rinominare la libreria
"fbembed.dll" in ""gds32.dll"
Credo che venga attribuito al cambio di database la causa di errori che sono invece imputabili all'applicazione e che non sono stati riscontrati nel primo caso per... puro caso.Originariamente inviato da Brendon77
Tutto andò bene, su un altro pc(senza server firebird) il programma funziona correttamente tranne per un cosa.....
nell'inserimento di una chiave primaria già utilizzata non compare il mio mesasggio di errore personale e in più viene inserito il record corrispondente (sempre in memoria.... nel database non ci sono modifiche).
Per me non è questo il problema.Originariamente inviato da Brendon77
Praticamente il comportamento da me progettato e sperato (l'invio del mio messaggio di errore e non inserimento del record me lo da se utilizzo il server Firebird)... se provo ad utilizzare la versione embedded ecco che tutto non funziona....
Direi di sì.Originariamente inviato da Brendon77
Penso di essere stato + chiaro e preciso....![]()
Usa la proprietà VendorLib, ed eviti questo passaggio.Originariamente inviato da Brendon77
Immagino che sia inutile fermare il server firebird se in una cartella c'è già la libreira del Firebird Embedded, penso che venga vista prima lei, ma volevo essere sicuro per avere la certezza....
Ciao!![]()

Definisci un indice sul componente CDS usando la proprietà IndexDefs e assegnandogli l'attributo di univocità, oltreché facendolo riferire al campo chiave.
Rispondi quotando