Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: schumi - Marzo 05, 2018, 10:30:13 am

Titolo: data module
Inserito da: schumi - Marzo 05, 2018, 10:30:13 am
Buongiorno,
ho un piccolo dilemma e non trovo niente in rete che fa al caso mio.
ho creato una form per gestire dei documenti (DDT, Fatture ecc) e un data module con anche tutto il codice per inserire modificare ecc.
Nella form dichiaro nelle variabili il mio DM e nel metodo formcreate uso il create(self), in formShow invece richiamo un metodo del DM che apre il filtro su DDT o fatture ecc.
Funziona tutto bene salvo quando apro 2 form, una ad esempio per DDT e una per Fatture, la seconda form apre gli stessi documenti della prima come se utilizzasse la stessa istanza della prima. Nella mia 'gnoranza credevo che un qualsiasi oggetto , anche un DM, potesse essere aperto ex-novo tutte le volte che si vuole e in maniera indipendente.
Uso ZeosLib su DB PostgreSql con una sola connessione al DB per tutte le query.
Dove sbaglio?

ricapitolando:
var
  frmDocumenti: TfrmDocumenti;
  dmDocumenti: TdmDocumenti; 

nel formcreate
dmDocumenti := TdmDocumenti.Create(self);

nel formshow
dmDocumenti.apri_Documenti(cTipo_documento) ;
Titolo: Re:data module
Inserito da: xinyiman - Marzo 05, 2018, 03:52:20 pm
Ciao Schumi, il problema, è che istanzi la finestra una volta, e quindi quando generi l'evento show della finestra ti apre sempre la stessa istanza. Tu devi creare un array di TfrmDocumenti.

var
  dmDocumenti: array of TdmDocumenti; 

E poi

nel formshow

SetLength(dmDocumenti,Length(dmDocumenti)+1);
dmDocumenti[Length(dmDocumenti)-1] := TdmDocumenti.Create(self);
dmDocumenti[Length(dmDocumenti)-1].apri_Documenti(cTipo_documento) ;

nel form hide devi poi fare un

for i := 0 to Length(dmDocumenti)-1
begin
   dmDocumenti[Length(dmDocumenti)-1].Free;
end;
Titolo: Re:data module
Inserito da: schumi - Marzo 05, 2018, 07:52:25 pm
faccio qualche prova con la tecnica degli array, vediamo se mi incarto.

grazie
ciao
Titolo: Re:data module
Inserito da: Stilgar - Marzo 05, 2018, 10:14:30 pm
Ma non serve  array.
Nel senso crei la form associata ad un'applicazione. Questa viene messa nella lista dei componenti dell'applicazione. Se fai un array crei un doppione.
Banalmente:
Codice: [Seleziona]
Application.createform (tipoform variabileform);
Variabileform.show;
Nella form puoi mettere un onclose che faccia la pulizia della memoria.
Lavori solo con una varibile alla volta. Il framework fa il resto.😉
Titolo: Re:data module
Inserito da: Stilgar - Marzo 05, 2018, 10:18:19 pm
Magari metti una property nella form figlia in modo da discriminare il tipo di documento da aprire prima di fare la show.
Titolo: Re:data module
Inserito da: schumi - Marzo 05, 2018, 11:29:46 pm
la form la creo al bisogno, quindi

var fmDocumenti: TfrmDocumenti;
....
fmDocumenti := TfrmDocumenti.Create(Self);
fmDocumenti.cTipo_documento := tipo_documento ;

fmDocumenti.show;
oppure
TDIMain.ShowFormInPage( fmDocumenti, 5 );
visto che sto testando l' interfaccia TDI con discreta soddisfazione.

ecco perché la funzione apri_documenti lo lancio nel show, il tipo documento è una variabile pubblica e finché non creo la form non esiste.

ora ho cambiato creando una property e una procedura SetTipoDocumento che lancia apri_documenti(), dmDocumenti è nella dichiarazione private, ma il risultato non cambia (anche se codice mi piace di più).

comunque se richiamo lo stesso datamodule da un'altra form che lancia altri metodi la storia si ripete.
dilemma ancora irrisolto, 2 form possono aprire lo stesso datamodule in maniera indipendente l'una dall'altra?
form1
form2
data1 che contiene query1
form1 lancia una select con query1
form2 lancia una select diversa sempre con query1

grazie
ciao
Titolo: Re:data module
Inserito da: schumi - Marzo 06, 2018, 09:24:34 am
trappolando un po' ho capito che il problema sono i datasource che ho messo direttamente nel datamodule.
consigliate di spostarli nella form?

grazie
ciao
Titolo: Re:data module
Inserito da: Stilgar - Marzo 06, 2018, 09:28:34 am
Ma no. Al massimo fai un data module nuovo per ogni form.
La form tiene il riferiamo al suo data module in modo da distruggerlo in chiusura.
In alternativa crei i datamodule che creano la form e si distruggono al freenotification della form collegata.
Ci sono tante opzioni per non spostare i dataset 😊
Titolo: Re:data module
Inserito da: schumi - Marzo 06, 2018, 10:43:17 am
ma in realtà si crea un datamodule nuovo per ogni form, le query sono corrette, mentre il datasource visualizza sempre le info del primo datamodule aperto.
spostando il dataset nella form pare funzionare tutto, solo un po' macchinoso creare i collegamenti:
datasource1.dataset := DataModule1.query1;

non trovo esempi evoluti di come utilizzare i datamodule, ma forse non li so cercare  ::) ::)
Titolo: Re:data module
Inserito da: schumi - Marzo 06, 2018, 12:05:10 pm
credo di aver risolto....San Google e un po' di apertura mentale (ho cercato come delphi)
ho trovato questo esempio su StackOverflow

if FDataModule = nil then
  begin
    FDataModule := TMyDataModule.Create(Self);
    FDataModule.Name := '';  // That will avoid pointing to the same datamodule
  end;
Titolo: Re:data module
Inserito da: Stilgar - Marzo 06, 2018, 12:09:48 pm
Allora.
Di base Form e DataModule sono componenti.
Ogni componente notifica quando viene distrutto. (FreeNotification).
Se il datamodule che istanzi, crea la form, basta mettere una property al datamodule con la form appena creata.
Aggiungi la onClose che distrugga l'istanza l'istanza.
Codice: [Seleziona]
 protected procedure TComponent.Notification( AComponent: TComponent; Operation: TOperation); virtual;
A questo metodo arrivano tutte le notifiche di distruzione e creazione dei componenti.
Quindi calando nel contesto il discorso.
Codice: [Seleziona]
TDataModuleController=class(TDataModule)
protected
   FView : TForm;
....
public
  property TargetView : TForm;
protected
  procedure Notification( AComponent: TComponent; Operation: TOperation); override;
...
  constructor Create(AOwner : TComponent);
end.

Constructor TDataModuleController.Create;
begin
  inherited Create(aOwner);
  Application.CreateForm(TForm, FView);
  FView.FreeNotification(self);
end;

procedure TDataModuleController.Notification( AComponent: TComponent; Operation: TOperation);
begin
  if (operation = opRemove) and (aComponent=FView) then
  begin
  FView := nil; // pulisci solo il riferimento, non eliminarlo, altrimenti incorri in errori di violazione.
   Destroy;
  end;
end;

Logicamente tutti i dataset e datasource li devi assegnare correttamente. Altrimenti comanda la configurazione fatta graficamente.
Titolo: Re:data module
Inserito da: Stilgar - Marzo 06, 2018, 12:10:52 pm
Codice: [Seleziona]
   FDataModule.Name := '';  // That will avoid pointing to the same datamodule
Questo serve a non far scattare un errore di "Nome duplicato"...
Titolo: Re:data module
Inserito da: schumi - Marzo 06, 2018, 02:28:29 pm
Nel mio caso sono le form che aprono i DM, per semplificare e non ripetere codice uso lo stesso DM su più form, il problema era che aprendo 2 o più form con lo stesso DM i dataset visualizzavano i dati della prima form aperta. Con la piccola modifica sopra il problema è scomparso.
Ammetto che ho risolto per tentativi non avendo cultura delphi alle spalle, solo parecchio turboPascal su DOS. :o :o :o

Manca un articolo sulla gestione "avanzata" dei DM (i tutorial che ho trovato in rete sono solo basici).
se qualcuno se la sente di cimentarsi.... ;) ;)

grazie