PDA

Visualizza la versione completa : [DELPHI] Invio di una lista di record


VaLvOnAuTa
25-05-2006, 10:18
Sempre un'applicazione client-server.
Il server è collegato ad un db MySQL.
I client possono richiedere al server una serie di informazioni (ad esempio i contatti di una rubrica i cui cognomi inizino per "A").
Ho davanti a me tre strade (almeno per quanto ne so :D):
1- Creare un DSN su tutte le macchine client, in modo che sia lo stesso client a fare la richiesta a MySQL (vorrei evitare... voglio lasciare libero il cliente di installare e disinstallare il programma senza dover agire sul sistema - il che vorrebbe dire che dovrei intervenire io ogni votla)
2- Il server elabora la richiesta e manda al client un contatto alla volta (va bene finchè i contatti son 10-20 ma su decine di record diventa laborioso e stupido)
3- Il server ed il client hanno un oggetto (od un record) che può contenere tutte le informazioni. Il server, elabora la richiesta del client, crea una lista di tali oggetti e la invia con uno stream al client. Il client "spacchetta" lo stream e lo elabora.

Credo che la 3 sia la strada più corretta. Ma non avrei idea di
- Come trasformare la lista di oggetti in uno stream "inviabile"
- Come fare l'operazione inversa
- Come fare a distinguere uno stream di "record" da un comando semplice.

VaLvOnAuTa
25-05-2006, 10:32
Ok.. forse una soluzione all'ultimo quesito l'ho trovata

TCommand = class(TObject)
comando: string[10];
opzioni: string[10];
dati : TList;
end;

VaLvOnAuTa
25-05-2006, 10:36
Mi sto rispondendo da solo però...
E se facessi un brutale casting dell'oggetto?
TStream(Command)

alka
25-05-2006, 10:43
Io non ho capito qual è il problema... :master:

VaLvOnAuTa
25-05-2006, 10:56
Sono stato troppo criptico, o intendevi dire che il problema non c'è? :fagiano:

Sostanzialmente, devo inviare tramite socket una serie di record di un database. Inviarli uno alla volta è una sciocchezza, quindi voglio (vorrei) inviarli in blocco.
Allora creo una lista di record, "streamizzo" tale lista e la invio al client. Solo che non so come "streamizzare" tale lista se non con un brutale casting: TStream(Lista)

E' un procedimento corretto, c'è qualche altro modo o ho proprio sbagliato l'impostazione della soluzione? :master:

alka
25-05-2006, 11:33
Presumo che tu possa crearti un "protocollo personalizzato" con cui impacchettare i dati e recuperarli alla ricezione.

Stabilirlo per un messaggio o per più messaggi è indifferente.

VaLvOnAuTa
25-05-2006, 11:46
type
TCommand = class(TObject)
cmd : string[10];
opt : string;
data: TList;
end;

TRubrica = class(TObject)
Nome,
Cognome: string[15];
Azienda: string[30];
NumTel,
NumCell: string[20];
Email,
Notes : string[30];
end;

// omissis

procedure TForm1.Button1Click(Sender: TObject);
begin
comando: TCommand.Create; // la variabile comando è dichiarata "private" nella classe del form
comando.cmd := 'GetList';
comando.opt := 'A'; // secondo il mio protocollo questo comando con quest'opzione chiede al server di fare una lista di contatti che comincino per A
IdTcpClient1.WriteStream(TStream(comando));
IdTcpClient1.ReadStream(TStream(comando)); // il client riceve risposta dal server ed inizia l'interpretazione dello stream.

// omissis

end;Però, a run-time il compilatore mi dà errore di access violation sul casting di "comando"; immagino sia perchè non è stato istanziato come stream. Allora ho creato anche una variabile temporanea di tipo TStream e l'ho inizializzata, ma mi dà sempre access violation.

alka
25-05-2006, 11:52
Originariamente inviato da VaLvOnAuTa
Però, a run-time il compilatore mi dà errore di access violation sul casting di "comando"
Per forza di cose: stai facendo il cast al tipo TStream di un oggetto che non è di quel tipo, né deriva in qualche modo da esso.


Originariamente inviato da VaLvOnAuTa
immagino sia perchè non è stato istanziato come stream.

Semplicemente, non è uno Stream.


Originariamente inviato da VaLvOnAuTa
Allora ho creato anche una variabile temporanea di tipo TStream e l'ho inizializzata, ma mi dà sempre access violation.
Hai sicuramente commesso un altro tipo di errore, ma senza il codice non posso verificarlo. :stordita:

VaLvOnAuTa
25-05-2006, 12:50
E se facessi ereditare TCommand da TStream?

alka
25-05-2006, 13:07
Se il tuo TCommand deriva da TStream, deve anche comportarsi come uno stream.

Il fatto che sia richiesto un tipo di dato specifico, TStream, deriva dal fatto che questo tipo fornisce metodi e proprietà specifici; creare uno stream personalizzato implica la ridefinizione di metodi per eseguire determinate operazioni e supportare, insomma, le funzionalità del nuovo tipo di stream.

Non è necessario in questo caso, secondo me.

Puoi sempre mantenere la struttura che preferisci per rappresentare il pacchetto dati da inviare, cioè il tuo TCommand. L'unica cosa che devi fare è copiare i dati della tua struttura all'interno di una delle classi che implementano TStream (che è astratta, come indicato nella Guida), come ad esempio TMemoryStream, che rappresenta semplicemente un flusso di dati in memoria. Usando i metodi di scrittura nello stream, devi copiare un "record" (inteso come serie di dati) al suo interno, inviarlo tramite Indy Components e, dall'altra parte, fare l'operazione inversa con i metodi di lettura dopo averlo ricevuto.

Non andare a tentoni però: consulta la guida sulla classe TStream e discendenti, reperisci documentazione ed esempi per capire come si utilizzano e, in seguito, applicali al tuo caso.

Ciao! :ciauz:

P.S.: ma perchè i tuoi client non possono prelevare i dati direttamente dal database MySQL? :stordita:

Loading