Newsgroup: it.comp.lang.delphi
Titolo: Sqlite, firedac e Ftp

Salve a tutti, scrivo per ottenere un vostro prezioso supporto/consiglio.
Sto realizzando una semplice rubrica per Android tramite Delhi 10, firemonkey e firedac. Il db che utilizzo per salvare i numeri di telefono nella memoria interna dello smartphone è SQLite.
Vorrei fare un'implementazione al programma, ossia sincronizzare i dati della rubrica prendendoli da un database salvato su un server. Poiché non ne so nulla di programmazione client/server, REST e datasnap mi è venuto in mente di usare Ftp. Nello specifico, pensavo di fare questo: alla pressione del pulsante"aggiorna" chiudo il database, cancello il file originale, scarico il database dal server tramite ftp, riapro il database. Sono riuscito a scrivere il codice ma c'è qualcosa che non va poiché ricevo un errore sql/firedac che mi dice:
"The database disk image is malformed". 
 
Cosa può essere successo? È corretto secondo voi questo procedimento? Ftp, applicato al mio caso specifico, può servirmi per ottenere ciò che vorrei fare?
 
Grazie a tutti in anticipo.

 "The database disk image is malformed". 
 
2 prove rapide da fare...
 
1) collegati al tuo ftp da un qualcosa che non sia la tua app e scaricati il file, poi prova ad aprirlo. 
 
2) collega il tuo device al pc e, usando la shell di adb copiati il file sul pc, prova ad arpire questa copia e vedi cosa succede
 
A.

 Lo strumento per sviluppare app android è android studio, punto.
 
Questo e` un tuo teorema. Ci sono vari modi per sviluppare su Android e Android Studio e` solo uno di questi. Se non conosci Xamarin, come fai a dirlo?

Ciao Alberto, innanzitutto grazie per avermi risposto.
 
Uso Delphi per lo sviluppo di applicazioni Android in quanto per prima cosa amo questo linguaggio alla follia :-) e poi perchè sono solo un appassionato di informatica e non lo faccio di mestiere, per cui non avrei proprio il tempo materiale di studiarmi ex novo un linguaggio.
 
 
Ti posto il codice associato all'evento OnClick di un pulsante:
 
FDConnection1.Connected := false;
 
DeleteFile(TPath.GetDocumentsPath + PathDelim + 'database.s3db');
 
  IdFTP1.Host := 'nomehost';
  IdFTP1.Username := 'user';
  IdFTP1.Password := 'pass';
  IdFtp1.Passive := false;
  IdFtp1.ConnectTimeout := 1000;
  try
    IdFtp1.Connect();
  except
    ShowMessage('impossibile connettersi');
  end;
 
  if IdFTP1.Connected then
    begin
      IdFtp1.BeginWork(wmRead);
      IdFTP1.ChangeDir( '/' );
      if not FileExists('database.s3db') then
        begin
          IdFTP1.Get( 'database.s3db', TPath.GetDocumentsPath + PathDelim +       
                        'database.s3db', true, false);
        end;
 
      IdFtp1.Disconnect();
    end;
 
  FDConnection1.Params.Values['Database'] := 
                     TPath.Combine(TPath.GetDocumentsPath, 'database.s3db');
  FDConnection1.Connected := true;
  FDQuery1.Active := true;
 
 
Quando clicco sul pulsante mi compare il seguente errore: [FireDAC][Phys][SQLite] ERROR: malformed database schema (?)
 
 
L'errore mi compare anche se sul server ftp carico lo stesso database originale.
 
Ripeto, è una soluzione alternativa che mi è venuta in mente per aggiornare da remoto i dati del db poichè non conosco la programmazione client/server.
 
Grazie!

Ftp, applicato al mio caso specifico, può servirmi per ottenere ciò che vorrei fare?
 
No.
 
Varrebbe la pena imparare come connettersi ad un db remoto ed importare i dati da esso. Non e` cosi` complicato.
 

Io cercherei di separare i problemi:
 
a) fare il download di un file via ftp
b) aggiornare un database rispetto ad una origine dati
 
Per il primo punto che il file sia un DB conta poco.
Devi riuscire a far funzionare il download in modo che il file che viene scaricato sia identico a livello binario (stessa dimensione, stessi byte, ...)
 
Per il secondo punto, in passato anch'io ho seguito una strada simile (scaricavo in realtà una tabella alla volta e non il database completo)
 
Ora ho realizzato (con parecchio lavoro) una gestione di sincronizzazione incrementale, in modo da non dover ogni volta ri-aggiornare tutto.
 
Il limite infatti del metodo che stai seguendo è la dimensione dei dati che devi scaricare.
 
Se si limitano a poche centinaia di record funziona correttamente.
Quando la dimensione arriva a migliaia, decine di migliaia o (come nel mio caso) centinaia di migliaia di record anche i tempi di sincronizzazione diventano importanti
 
Per ultimo, riguardo al consiglio di connetterti al DB da remoto avrei una critica: di solito quando utilizzi un DB remoto viene impostato nel server che questo possa essere utilizzato solo da applicazioni locali (per ragioni di sicurezza).
 
Per poter accedere da remoto devi quindi aprire delle porte nel firewall per consentire l'accesso: le porte sono standard e quindi attaccabili...
 
Io ho preferito seguire la strada di un web service (scritto per l'occasione in PHP) che fa da interfaccia tra le mie chiamate e il DB remoto.
 
Avrei anche potuto scrivere una applicazione con RAD Studio 10.2 in linux, ma la pigrizia e il tempo a disposizione mi ha fatto optare per PHP.
P.S. io utilizzo solo server Linux esposti nel web (è una scelta personale)
 

Vorrei fare una aggiunta circa quanto riguarda utilizzare Delphi per sviluppare una APP Android.
 
Sicuramente per un nuovo progetto è valido il suggerimento di strumenti diversi.
 
Ma se devi "riutilizzare" parte del tuo codice?
E se devi fare una applicazione che possa girare anche su IOS o MAC?
 
Personalmente ho una APP che ho scritto in Delphi (Android) nella quale ho riutilizzato circa 500.000 linee di codice... tratte da uno dei miei progetti a cui lavoro da anni che ha circa 2.100.000 linee di codice
 
Quanto tempo avrei impiegato a riscrivere quelle righe?
 
N.B. Ovviamente questo è il mio parere personale

> Varrebbe la pena imparare come connettersi ad un db remoto ed importare i dati da esso. Non e` cosi` complicato.
 
 
Quindi cosa mi consigliate per imparare a connettermi a un db remoto? Che guide/manuali posso leggere?
Non saprei proprio da dove iniziare.
 
Grazie! 

 Non saprei proprio da dove iniziare.
Prova a partire da qui!!!
 
Ciao
 
Daniele 
 

Ciao,
non ci sono differenze sostanziali nel connettersi a un DB locale rispetto a uno remoto, tranne la velocità di risposta. Le credenziali e i parametri sono gli stessi (hai bisogno ovviamente dell'indirizzo IP del server)
 
Ci sono differenze di configurazione nel server / firewall che deve consentire la connessione da remoto (alcuni provider non la danno neppure come possibile...)
 
Devi però iniziare a "pensare" in modo diverso: quando fai una elaborazione su un sistema remoto devi pensare che il fetch dei record (caricamento di un recordset in memoria) è molto dispendioso in termini di tempo.
 
Quindi devi fare di tutto per evitare questa situazione.
La cosa migliore è lavorare con comandi che non prevedano il "ciclo" su tutti i record di una query.
 
Ovviamente ci sono varie strategie al riguardo, tra cui inserire un campo che contenga la marcatura temporale dell'ultima modifica fatta su un record
 
Devi pensare anche a come gestire i record cancellati (che ovviamente non ci sono più nel database di origine...) e vanno rimossi in quello da sincronizzare.
 
Se poi sei in un progetto professionale, potresti anche utilizzare delle funzioni disponibili in alcuni motori database che gestiscono direttamente sincronizzazioni dati.
Ad esempio SQL Server (non la versione Express...), oppure MariaDB / MySql

 credenziali di accesso
 
 
Ciao Daniele,
 
ho capito la logica sottostante ma avrei bisogno di leggere qualcosa a riguardo (demo, manuali, ecc.), perché non saprei proprio che codice scrivere. Inoltre sul server, a parte aprire le porte, devo fare qualcos'altro o è sufficiente salvare solo il database?
Per fare tutto ciò, posso anche utilizzare i servizi di hosting gratuiti?
 
Sul web ho visto che ci sono delle guide per l'utilizzo dei componenti DataSnap con i server Rest. Potrebbero fare al caso mio? Se sì, come si utilizzano?
 
Grazie!
 
 
p.s.: sono riuscito a risolvere il mio problema! Il codice era corretto, bisognava solo cambiare una proprietà del componente TIdFtp: da ASCII a Binario. I tempi della procedura sono anche abbastanza veloci, considerando che il database pesa circa 500Kb.
 

>quando fai una elaborazione su un sistema remoto devi pensare che il fetch dei record (caricamento di un recordset in memoria) è molto dispendioso in termini di tempo. 
Quindi devi fare di tutto per evitare questa situazione. 
La cosa migliore è lavorare con comandi che non prevedano il "ciclo" su tutti i record di una query. 
Ovviamente ci sono varie strategie al riguardo, tra cui inserire un campo che contenga la marcatura temporale dell'ultima modifica fatta su un record 
Devi pensare anche a come gestire i record cancellati (che ovviamente non ci sono più nel database di origine...) e vanno rimossi in quello da sincronizzare 
 
 
Ciao Alessandro,
ci sono degli esempi di codice da poter studiare? 
Con i servizi di hosting gratuito si può realizzare?
 
Grazie.

 Devi però iniziare a "pensare" in modo diverso: quando fai una elaborazione su un sistema remoto devi pensare che il fetch dei record (caricamento di un recordset in memoria) è molto dispendioso in termini di tempo.
 
E` sicuramente meno dispendioso che estrarre i dati, salvarli su file, metterli a disposizione su un server ftp, scaricare il file ed importarlo nel sistema.

 anche abbastanza veloci, considerando che il database pesa circa 500Kb.
Non sembra un grande db (mezzo mega!!)
Il db su cui lavoro io e' composto da (circa) 700 tabelle e pesa 5 gb ..... 
e non e' tra i piu' imponenti !!!
 
Spero tu riesca a risolvere in breve tempo !!!
 
Ciao
 
Daniele 
 

Confermo che questa è proprio l'operazione che sconsiglio di fare.
Estrarre, fare upload ftp, scaricare da ftp, ricaricare, ...
 
Io suggerivo: se in DB con 100.000 record e dall'ultima verifica ne sono stati cambiati 100, perché trasferire tutti i 100.000 record?
 
Non è una cosa semplice da fare, ma aggiornare solo i 100 record modificati è molto più efficente

 Con i servizi di hosting gratuito si può realizzare?
Sinceramente non saprei.
Per i servizi web utilizzo dei miei server e mai servizi in hosting
 
 

Eh e chi dice che si debba scaricare tutto?

 N.B. Ovviamente questo è il mio parere personale
 
Tranquillo! :-D
 
A.
 

 Per ultimo, riguardo al consiglio di connetterti al DB da remoto avrei una critica: di solito quando utilizzi un DB remoto viene impostato nel server che questo possa essere utilizzato solo da applicazioni locali (per ragioni di sicurezza).
 
Si`, e` probabile che il db in questione sia blindato per cui non accessibile direttamente (l'OP parla di db "su un server" senza aggiungere altro). Se e` quello il caso, "consumare" un'API REST di solito e` cosa banale da fare. 

> Si`, e` probabile che il db in questione sia blindato per cui non accessibile direttamente (l'OP parla di db "su un server" senza aggiungere altro). Se e` quello il caso, "consumare" un'API REST di solito e` cosa banale da fare.
 
Confermo che era questo che intendevo

 
Questo è il mio cruccio maggiore

 Questo è il mio cruccio maggiore
 
Il problema è sempre legato al rapporto tra il tempo disponibile e quello da dedicare a mutuo&pagnotta.
 
 
A.