Newsgroup: it.comp.lang.delphi
Titolo: [DB] usare una connessione db in più form

Ciao a tutti, avrei la necessità di usare una connessione ad una base
dati in più form, cosa mi consigliate?
Per il momento utilizzo una ADOConnection con visibilità globale
(creata a runtime), ma ora ho la necessità di collegarci dei controlli
data-aware.
Consigli? Idee? Grazie
Matteo

 dati in più form, cosa mi consigliate?
Ti suggerisco di aggiungere al tuo progetto un *Data Module*: è una 
specie di "contenitore" in grado di contenere, appunto, componenti di 
vario tipo. Molto spesso, come suggerisce il nome stesso, si tratta di 
componenti per l'accesso ai dati.
Nel tuo caso, inserisci nel Data Module il componente *ADOConnection*; 
selezionando il menu [File|Use Unit] quando il form è selezionato, 
potrai aggiungere la unit del Data Module alla clausola uses e quindi 
accedere ai componenti del modulo, tra cui la ADOConnection per 
collegarti al database in esame.
Attraverso i componenti *ADOTable*, *ADOQuery* e così via, 
eventualmente posti sul form, puoi accedere alla connessione 
impostando la proprietà /Connection/ al componente che hai inserito 
nel Data Module (che deve essere aperto).
Attraverso un componente *TDataSource*, infine, puoi instaurare un 
collegamento tra qualsiasi Data Control tra quelli disponibili 
(DBGrid, DBEdit e così via) e il DataSet utilizzato (ADOTable, 
ADOQuery, ecc. che sia).
E' necessario modificare le "Project Options" per accertarsi che il 
Data Module venga creato automaticamente (e di solito prima di 
qualsiasi form, incluso il form principale) all'avvio 
dell'applicazione; inoltre, puoi inserire le chiamate ai metodi /Open/ 
e /Close/ di ADOConnection negli eventi /OnCreate/ e /OnDestroy/ del 
DataModule.
Dal contenuto della tua domanda, sospetto che tu sia ancora alle prime 
armi sull'argomento "Accesso ai dati con Delphi"... prova a reperire 
della documentazione a riguardo prima di accingerti ad affrontare 
problematiche serie per non incappare in una strutturazione del tuo 
applicativo che sia da rivoluzionare in seguito, quando avrai una 
certa esperienza. ;-)
Ciao! :-)
-- 
Marco «Alka» Breveglieri
  ABLS Team S.n.c. - Software & Web
  Via De Gasperi, 14
  42019 Scandiano (Reggio Emilia)
 
http://www.abls.it



Prsonalmente sono solito posizionare il componente TADOConnection nel form
principale dell'applicazione: Marco Breveglieri ti suggerisce di usare il
TDataModule, che è una gran cosa, però con i componenti ADO mi è capitato
più volte che gli oggetti ADOQuery nei vari form "perdessero" il
collegamento all'ADOConnection, al punto di costringermi a forzare a
runtime il collegamento con questo ciclo nell'evento Create dei vari form
  for i := 0 to ComponentCount - 1 do
    if Components[i] is TADOQuery then
      TADOQuery(Components[i]).Connection := DataModule1.ADOConnection1;
Mettendo l'ADOConnection nel form principale non mi è invece mai successo:
scegli tu (la prassi corretta comunque è quella di usare i DM).
Saluti
	Marco Bortolani
	info @ 
marcobortolani.it
P.S.
Con "perdessero il collegamento" intendo che in una successiva riapertura
del progetto trovavo la property Connection dei vari oggetti TADOQuery
impostata a blank - o "non impostata" :-((
Uso Delphi 7 Pro aggiornato

 impostata a blank - o "non impostata" :-((
Ho sentito parlare (e riscontrato) questo bug quando si utilizzano i 
componenti per l'accesso ai dati (qualsiasi) su form e si creano dei 
"discendenti" di tali form; quando il componente sul form fa 
riferimento ad un modulo esterno e si apre uno dei discendenti - senza 
aprire prima il modulo esterno - tale riferimento viene come perduto.
E' il tuo caso?
Adesso che mi ci fai pensare, non ho ancora verificato se Delphi2005 
contiene ancora questo bug...verificherò. :-)


"
Mat...@none.org
" ha scritto nel messaggio

Non so se può essere utile, io in genere organizzo i progetti di una certa 
dimensione in questo modo:
- in un datamodule metto tutte le connessioni a database (TAdoConnection 
oppure TDatabase) di cui necessito. Generalmente solo una, ma non 
necessariamente. Questo datamodule viene creato all'avvio ed è usato da 
tutte le unit/form che utilizzano l'accesso ai dati;
- organizzo gli oggetti di accesso (TAdoTable, TAdoQuery, ecc) in vari 
TDataModule in relazione alle varie aree funzionali dell'applicazione. In 
questi definisco tutti i fields come persistenti (ma questa è una mania 
mia). Ovviamente gli oggetti sono collegati alle connessioni di cui sopra. 
La creazione automatica di questi non mi interessa, anzi, al 99% dei casi 
cancello la dichiarazione della variabile associata ai singoli TDataModule;
- nelle form metto gli oggetti visuali di accesso ai dati e li lego ad uno o 
piu TDataSource, che ovviamente a Design vanno a puntare ai vari DataSet 
definiti nei vari TDataModule. Quindi l'"uso" di uno o l'altro TDataModule 
dipende da come ho organizzato le varie aree funzionali;
- a questo punto dichiaro come membri private del Form i singoli TDataModule 
di cui ho bisogno (dm1: TDataModule1; ecc.);
- nell'evento Create del Form (o nello Show, se il form è autocreate) 
istanzio i miei TDataModule privati e faccio in modo che i TDataSource 
puntino ai dataset necessari;
- in situazioni particolari, posso anche assegnare agli eventi dei dataset 
delle routine locali, in modo da ottenere dei comportamenti specifici per il 
form;
- nell'evento Destroy del Form dealloco i TDataModule locali.
Qualcosa tipo:
TfrmCarSca = class(TForm)
  datiSILOS: TDBGrid;
  dsSilos: TDataSource;
  [...]
  procedure FormCreate(Sender: TObject);
  procedure FormClose(Sender: TObject; var Action: TCloseAction);
  [...]
private
  dmDsTB: TDmDosaggioTb;
  [...]
  procedure tbSilosArticoloValidate(Sender: TField);
  [...]
public
  property DataModule: TdmDosaggioTb read dmDsTB;
end;
procedure TfrmCarSca.FormCreate(Sender: TObject);
begin
  { Creazione del Datamodule contenente le tabelle di uso comune }
  dmDsTB := TdmDosaggioTb.Create(Self);
  dmDsTB.fldSlsArticolo.OnValidate := tbSilosArticoloValidate;
  dsSilos.DataSet := dmDsTB.tbSilos;
  dmDsTB.tbSilos.Filtered := True;
  dmDsTB.tbSilos.Active := True;
  dmDsTB.tbSilos.Refresh;
end;
procedure TfrmCarSca.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  dmDsTB.tbSilos.Filtered := False;
  dmDsTB.tbSilos.Cancel;
  dmDsTB.tbSilos.Active := False;
  dmDsTB.fldSlsArticolo.OnValidate := nil;
  { Distruzione del DataModule contenente la base dati }
  dmDsTB.Free;
end;
Naturalmente poi nel codice farò sempre riferimento all'oggetto privato e 
non al DataModule globale (anche perchè avendone cancellato la dichiarazione 
sostanzialmente non esiste piu).
Il piu grosso vantaggio di questa soluzione è che mi permette di gestire 
applicazioni dove ho piu maschere aperte sulla stessa tabella senza 
necessariamente essere legato ad un solo cursore, pur mantenendo tutto il 
codice di gestione all'interno di un solo DataModule.
Lo svantaggio, naturalmente, è quel pò di codice da scrivere in piu in fase 
di inizializzazione della maschera.
Ciao,
Gianluca.

 E' il tuo caso?
In verità non è questo il mio caso: ho usato una configurazione come quella
da te descritta solo in una serie di applicazioni su db PostGreSQL, quindi
niente ADO (ho usato gli Zeos).
Io parlo di un semplice programma con il DbConnection su un datamodule e
una serie di form che vi fanno riferimento: in alcune form secondarie (es.
i modulini che utilizzo per implementare i wizard di caricamento dati) gli
oggetti TADOQuery "perdevano" la property Connection, senza alcun apparente
motivo, come se venissero creati prima che fosse creato il datamodule con
l'oggetto connessione... 
Uhm... 
Vuoi vedere che ho capito perchè perdevano la property? Non ho controllato
l'ordine di creazione dei form... AAAARGH! A letto senza cena.


 l'ordine di creazione dei form... AAAARGH! A letto senza cena.
Inchesssenso?
(da leggersi in stile Mimmo interpretato da Carlo Verdone)
