Newsgroup: it.comp.lang.delphi
Titolo: [D2005] Web Service

Salve a tutti,
prosegue il mio periodo di test sul nuovo ambiente D2005 e ovviamente
sono assalito da mille dubbi.
Sto realizzando un semplice web service che deve fornire informazioni
recuperate da una base dati (utilizzo Firebird con i data provider
scaricati dal sito 
www.firebird.it
).
Il mio problema è capire la squenza con cui vengono chiamati il
costruttore ed i vari metodi dell'oggetto "servizio".
Mi spiego meglio.
Quando in delphi inizio un progetto "web service" l'IDE mi prepara una
classe con tanto di costruttore che rappresenta il mio servizio sul web,
a questa classe ho aggiunto i metodi che voglio esporre sul web.
Dal momento che i metodi del mio servizio devono accedere al database
avevo pensato di aprire la connessione al database nel costruttore (la
"Create" per capirci) della classe e di chiuderla nella "dispose".
Tutto funziona bene, il problema è che quando un client invoca un metodo
non parte solo la procedura del metodo che e' stato chiamato, ogni volta
parte anche il costruttore della classe.
Ad ogni chiamata del client corrisponde quindi:
Create
MetodoChiamato
Dispose
Risultato: la connessione al database è aperta e chiusa ad ogni utilizzo
di un metodo da parte del client.
Faccio notare che il client (nel mio caso un'applicazione Win Forms
.NET) dichiara una variabile della classe relativa al web service e la
crea una sola volta in tutto l'arco di esecuzione.
Grazie mille.
Alfredo

 crea una sola volta in tutto l'arco di esecuzione.
La classe che rappresenta il Web Service nel progetto Client rappresenta 
sostanzialmente un "wrapper" al servizio pubblicato sul Web.
Creare un'istanza di tale classe non significa creare un'istanza del 
servizio in quanto tale, ma solo l'istanza di un "proxy" che consente di 
interfacciarsi con il servizio.
Il Web Service viene esposto attraverso una pagina .ASMX; quando tale 
pagina viene invocata dal client attraverso la classe proxy, allora il 
server provvede ad istanziare la classe del Web Service per assolvere le 
richieste, comportandosi così come hai descritto nel tuo messaggio.
Se vuoi aprire la connessione al database e mantenerla aperta tra una 
invocazione e l'altra dei metodi del Web Service, credo sia opportuno 
inserire la configurazione e l'apertura della connessione all'interno 
del file GLOBAL.ASAX, memorizzando il riferimento dell'oggetto che 
implementa IDBConnection nello stato dell'applicazione 
(HttpApplicationState) in modo da poterlo estrarre e utilizzare nella 
classe del Web Service tutte le volte che si vuole.
La configurazione e apertura della connessione viene effettuata 
nell'evento Application_Start, mentre la chiusura nell'evento 
Application_End, implementati nella classe cui fa riferimento il file 
GLOBAL.ASAX e che viene poi compilata nell'assembly in cui convoglia 
tutto il codice del progetto, rappresentato dalla DLL monolitica che 
ottieni (da copiare nella sottocartella "bin").
Spero di averti fornito indicazioni utili.
Fai qualche ulteriore prova e poi fammi sapere...
Ciao! :-)
-- 
Marco «Alka» Breveglieri
  (marco [@] abls [.] it)
  ABLS Team S.n.c. - Software & Web
  42019 Scandiano (Reggio Emilia)
 
http://www.abls.it

Marco «Alka» Breveglieri
	Ciao
	MassimoB
 
---------------------------
http://www.massimobeschi.it/

 al server DB. [...]
Ciao,
   forse non ho capito bene ciò che intendi oppure le casistiche a cui 
ti riferisci, ad ogni modo cerco di spiegare le implicazioni della mia 
soluzione riallacciandomi a quello che hai detto tu.
E' vero che la chiusura delle connessioni alle basi di dati (o la 
distruzione di risorse non gestite, in generale) non andrebbe affidata 
al Garbage Collector, poichè non è possibile determinare quando il GC 
entrerà in azione, occupando inutilmente risorse e generando in alcuni 
casi fastidiosi effetti collaterali.
Tuttavia, non sembra il caso della mia soluzione. Mi spiego.
La chiusura della connessione viene effettuata quando l'applicazione 
ASP.NET
 termina: il codice inserito nel metodo Application_End del 
GLOBAL.ASAX chiude la connessione, mentre in Application_Start avviene 
l'apertura.
In questo caso, è vero che la connessione rimane aperta dopo aver 
invocato un metodo del Web Service, ma è anche vero che non ne vengono 
aperte altre e l'uso di un'unica connessione già configurata e aperta 
all'avvio dell'applicazione rende l'invocazione di metodi in successione 
più performante.
Ad ogni modo, sono d'accordissimo con te sul fatto che la connessione 
non andrebbe creata e distrutta assieme alla classe che definisce il Web 
Service: piuttosto, è meglio aprire la connessione all'interno del 
metodo che viene invocato da remoto e, attraverso l'uso del costrutto 
try...finally, garantire la chiamata del metodo /Close/ qualsiasi cosa 
accada.


 performante.
questo è utile per generare casini che saranno evidenti solo in produzione 
quando ci saranno più utenti ad utilizzare l'applicazione e di conseguenza a 
condividere la connessione (cosa assolutamente non possibile).
La collection Application è condivisa da tutti gli utenti dell'applicazione, 
eventualmente, e dico eventualmente perchè per me è un approccio 
completamente errato, la si può mettere nella collection Session.
I miei consigli sono:
- aprire e chiudere le connessioni solo quando servono e e per il solo tempo 
necessario ad effettuare le operazioni sul db
- utilizzare il meccanismo di connection pooling che è presente all'interno 
del provider .net di Firebird
- creare un'eventuale helper class (o modificare la vecchia DAAB di 
Microsoft - oggi Enterprise Library) per le più comuni operazioni sul db
--
Alessandro Petrelli. 

 completamente errato, la si può mettere nella collection Session.
La connessione al database è condivisa da tutte le pagine 
indipendentemente dagli utenti che accedono, pertanto non vedo perchè 
dovrebbe trattarsi di un oggetto di sessione.


 dovrebbe trattarsi di un oggetto di sessione.
Proprio per quanto riportato sopra, Application è condivisa tra tutti gli 
utenti, Session è univoca per utente, di conseguenza un utente=una 
connessione...ma come ho già detto per me è completamente sbagliato 
l'approccio ;-)
--
Alessandro Petrelli. 

 l'approccio ;-)
Credo di aver compreso il tuo discorso (sono duro, ma piano piano 
arrivo): a ciascun utente corrisponde una connessione, concettualmente 
come se il mezzo HTML fosse trasparente ed egli si collegasse 
direttamente alla base dati; siccome le operazioni che l'utente esegue 
sulla base dati si concludono con l'invocazione di un metodo (Web 
Service) o la chiamata di una pagina, conviene chiudere tale connessione 
immediatamente, liberando le risorse quanto prima.
Per questioni di performance, se diventano un problema, dovrei fare 
affidamento sul "pool di connessioni" che viene già gestito 
autonomamente dal provider .NET.
Farò tesoro di queste nozioni...poi ci si chiede a cosa servono i 
newsgroup?? :-D


 newsgroup?? :-D
:-)
Ciao!
--
Alessandro Petrelli. 

 Ciao!
Ciao e grazie della conversazione! :-)


richiesta, Borland pensa di implementarla in occasione di 
ASP.NET
 2.0.
sai per caso qualche voce di corridoio su come si
coporterà Borland con Delphi e l'uscita (prossima) del
framework 2.0?


 framework 2.0?
Da quanto ho letto, la nuova versione del framework sarà supportata da 
una nuova versione di Delphi (e di Visual Studio).
A tal proposito, pare che l'uscita di "Whidbey" sia stata spostata 
leggermente a inizio autunno del 2005.


ad utilizzare BDP.
ok grazie


Ho potuto leggere il NG solo adesso e non so cosa dire... speravo in una 
risposta ma mai avrei pensato di trovare una cosi' esauriente serie post!!!
Dopo aver letto con attenzione ho chiaramente deciso di non attivare la 
mia connesione nel "Global.asax", ma piuttosto di farlo ogni volta che i 
dati sono necessari.
Devo poi approfondire l'argomento "Connection pooling", la teoria mi è 
chiara, al momento non so nella pratica cosa devo fare.
Credo che debba cercare nella documentazione scaricata insieme al 
provider .net di Firebird!
Grazie tutti
Ciao
Alfredo
PS: per la cronaca quanto suggerito da Marco Breveglieri nella prima 
risposta funzionava esattamente come descritto.

 .net di Firebird!
Devi solo aggiungere alla connectiong string
";Pooling=true;Connection Lifetime=secondi_di_vita_della_connessione;Min 
Pool Size=numero_min_connessioni;Max Pool Size=numero_max_connessioni".
Connection Lifetime se vale 0 significa che la connessione resterà sempre 
attiva (sconsiglio).
Max Pool Size (facoltativo) viene normalmente usato se il db server è 
condiviso tra più applicazioni e c'è necessità di limitare il numero massimo 
di connessioni.
Min Pool Size (facoltativo) serve per avere un numero minimo di connessioni 
sempre attive (utile se si accede al db via wan).
I due nomi sono inconsistenti con altre implementazioni e verranno cambiati 
a breve in MaxPoolSize e MinPoolSize.
Fatto ciò ogni volta che chiudi e apri una connessione il tutto viene 
gestito in automatico ed è per te completamente trasparente.
Ti consiglio inoltre, se non lo hai già fatto, di scaricare l'ultima 
versione stabile (1.6.3) dal sito 
www.ibphoenix.com
 o 
www.firebirdsql.org
.
Ciao.
--
Alessandro Petrelli.