Interfacciamento di database su web con ASP ed ADO
Introduzione
Una applicazione web utilizza un sito web come front end per una tradizionale applicazione.
La distinzione tra sito ed applicazione web risiede nella capacità del client di attuare la logica
(business logic) implementata sul server. La business logic fondamentalmente specifica quale è il
comportamento dell’applicazione, e quindi la sua uscita, a fronte di certi ingressi applicati.
Un’applicazione web è tale se è possibile modificarne lo stato, dove lo stato è qui inteso come
l’insieme dei dati gestiti dall’applicazione stessa. Un altro punto di vista è quello di considerare lo
stato del client. Chiariamo meglio questo concetto.
Innanzitutto l’interazione tra browser e server web è, come accennato, tipicamente costituita dalle
richieste effettuate dal client e dalle risposte ritornate dal server. E questo grazie ad un protocollo di
comunicazione, il protocollo HTTP, il quale però per natura non tiene traccia delle connessioni
precedenti.
Tali richieste possono essere pensate come ingressi indirizzati all’applicazione. Se gli ingressi sono
accompagnati da dati aggiuntivi (vedremo quali), è possibile comunicare al programma
un’informazione che consente, come detto, di specificarne il comportamento. L’architettura tipica delle
applicazioni Web è quella denominata 3-tier, a tre livelli, formata essenzialmente da tre unità logiche,
ossia:
Un Web Browser (client)
Un Web Server (server)
Un Database
In questi appunti verrà illustrato come con la tecnologia ASP la realizzazione di un’applicazione
web con uso di Database sia qualcosa di semplice ed immediato.
ODBC e ADO
ODBC (Open Database Connectivity) è una interfaccia di programmazione (una API Application
Program Interface) standard ed aperta per l’accesso a database. Originariamente rilasciata nel 1992,
consente di accedere a database di numerosissimi costruttori, inclusi Microsoft (jet, Access,
SQLServer); Oracle, IBM, Informix e numerosi altri. Si tratta, sostanzialmente, di uno strato software
che si interpone tra l’applicazione e i driver specifici del database. Consente quindi ai programmi
applicativi di usare richieste standard SQL, che accederanno al database, senza necessità di conoscere
la particolare interfaccia proprietaria.
ODBC è stato sicuramente un grande progresso nella programmazione di DB, ma richiede una certa
familiarità di programmazione con le API ed è sostanzialmente procedurale (Scritta in C).
Successivamente Microsoft ha introdotto altre due API, questa volta orientate agli oggetti, che vanno
sotto il nome di DAO (Data Access Object) e RDO (Remote Data Object), che sono sostanzialmente
interfacce per il motore ODBC. Esse definiscono interfacce ActiveX (originariamente COM
Component Object Model). Più recentemente Microsoft ha presentato ADO (Active Data Object),
basata su una nuova tecnologia di programmazione delle interfacce per DB nota come OLE DB
(Object Linking and Embedding for DataBases).
La differenza sostanziale con ODBC è che in questo ogni ogni tipo di DB deve avere una DLL
(Dynamic Link Library), un driver ODBC, che viene utilizzata dal motore ODBC per accedere allo
specifico DB. In OLE DB is hanno ancora dei driver, ma questi sono implementazioni ActiveX, cioè
definizioni di classi che implementano delle interfacce, eliminando così i livelli interposti tra il
programma e lo specifico DBMS che si sta utilizzando.
Attualmente è comunque possibile utilizzare un driver ODBC da OLE DB.
ADO e ASP
ASP fornisce tutte le funzionalità delle applicazioni CGI e ISAPI in modo più efficiente:
con le CGI il server crea un numero di processi pari al numero delle richieste del client
causando un aumento dell’utilizzo della RAM e impiegando in modo critico tutte le risorse
del sistema con conseguente caduta di performance e aumento del tempo di attesa;
le applicazioni che usano ISAPI sono compilate come link dinamici a delle librerie e sono
caricate dal servizio WWW. Le applicazioni ISAPI risiedono in memoria e sono più veloci
rispetto a quelle scritte tramite la tecnica CGI. Le applicazioni ISAPI richiedono meno
overhead perché ogni richiesta non parte come un singolo processo; ma supportano un grado
di complessità più elevato a differenza delle active server page quindi più difficili da gestire.
ASP utilizza tecniche multithread per consentire l’accesso ad un numero maggiore di utenti
eseguendo nello stesso processo più richieste.
ASP include supporti nativi per eseguire script in VBscript e Javascript, supporta inoltre l’uso di un
qualunque linguaggio di scripting, introducendo uno scripting engine, e di componenti scritti in un
qualunque linguaggio incluso Java, C++, Cobol, Visual Basic. Un linguaggio di scripting è necessario
per gestire la logica di collegamento, tra i vari elementi della pagina. Gli script e i componenti che
sono processati sul server forniscono in output un documento html standard in modo tale che gli active
server page possono lavorare con un qualunque browser; inoltre non viene effettuata nessuna
compilazione manuale: compilatori Just-in-time automaticamente ricompilano un file asp quando
richiesto caricandolo nella cache del server, in modo che i cambiamenti al file possono essere resi
visibili immediatamente.
Quando si creano oggetti con ASP si creano in pratica oggetti OLE (Object Linking and
Embedding) o ActiveX Component. Tramite gli OLE gli utenti possono creare documenti "contenitori"
che comprendono parti gestite da altri programmi, gli OLE si basano sul modello COM (Component
Object Model). Tutta la specifica di ActiveX, essendo integrata nella specifica OLE, si basa su questo
modello. COM fornisce l’architettura e il meccanismo per creare component che saranno condivisi tra
applicazioni. Sulla base del modello COM è stato definito DCOM (Distribuited Component Object
Model) che definisce una specifica e una implementazione delle interfacce tra oggetti attraverso la rete.
ActiveX Server Component conosciuti anche come OLE Automation Servers sono parte
dell’applicazione web ma possono essere usati al di fuori del contesto web favorendo il riuso del
codice. Il concetto è che è possibile utilizzare un component non solo da un ambiente di sviluppo
visuale o in un’applicazione OLE-enabled ma anche in una pagina web, i programmi scritti per il web
potranno essere utilizzati in una qualunque altra applicazione OLE-enabled.
I component sono oggetti con una piccola differenza: il component è sempre un package separato
dall’applicazione come una dll o come un oggetto COM e può essere immediatamente integrato nello
script per un suo utilizzo creando un’istanza.
ASP lavora con Active Server Object e Component già pre-costruiti fornendo un ambiente per
costruirne dei propri.
Di seguito vengono analizzati una serie di Active Server Object inclusi nell’ambiente Active Server
Page:
Request : fornisce l’accesso a qualunque informazione passata in uno script command con una
richiesta http proveniente da una forms, una query URL o da un’intestazione http.
Response: è responsabile della gestione dell’interazione del server con il client, è usato per
costruire i messaggi di risposta verso il browser.
Application: permette di settare le proprietà di un oggetto in modo da preservare lo stato
quando più utenti accedono contemporaneamente, è usato per memorizzare informazioni
comuni che sono condivise tra tutti gli utenti di una singola applicazione.
Session: permette di memorizzare e gestire tutte le informazioni necessarie ad un utente in una
particolare sessione. Il ciclo di vita di una sessione non si esaurisce saltando da una pagina
all’altra bisogna effettuare un richiesta diretta. Le variabili memorizzate nell’oggetto session
non vengono perse quando l’utente salta da una pagina all’altra nell’applicazione, ma sono
persistenti per l’intera sessione utente. L’obiettivo dell’oggetto session deve essere capito nel
contesto in cui è inserito. Le transizioni tra un browser ed un web server sono indipendenti
(state less) e mantenere un tracking di un utente risulta un compito arduo: Una proprietà di un
oggetto definito come session può essere referenziata su una qualsiasi pagina, in un qualunque
momento all’interno del ciclo di vita di una sessione utente; è un modo per correlare le
informazioni da una pagina all’altra.
Server: permette ad un script di creare un’istanza di un ActiveX Server Components,
indispensabile per accedere a qualsiasi component da un’applicazione web.
I components sono una delle caratteristiche più importanti delle Active Server Page. Essi sono
dll che vengono eseguiti nello spazio di indirizzi di un file asp e di IIS, ed offrono direttamente
l’accesso al sistema operativo. Di seguito una serie di components di base forniti insieme alla
Active Server Page:
Content Linking Component: Gestisce una lista di URL cosicché si possono trattare le pagine
di un sito web come se fossero pagine di un libro.
Filesystem Component: Fornisce accesso in lettura a un file di testo memorizzato sul server.
Browser Capabilities Component: Consente di determinare la capacità, il tipo e la versione
dei browser che accedono al web server in modo da ottimizzare dinamicamente il contenuto
delle pagine diversificando le risposte, proprio in funzione del browser connesso.
Advertisement Rotator Component: automaticamente rende visibile diversi cartelloni
pubblicitari in una pagina web in accordo a specifiche impostate dall’utente. Semplifica la
gestione delle immagini e produce notevoli effetti visivi come ad esempio la rotazione delle
figure.
ActiveX Data Object Component: Fornisce l’accesso a un database da un’applicazione web
mediante Active database Object (ADO). ADO fornisce un semplice accesso per mezzo di
ODBC standard a Micorsoft Access, SQL Server, Oracle, Informix , Sybase.
I web browser inoltrano la richiesta di accesso ai dati usando il protocollo HTTP su cui si basa
Internet. La risposta consiste in un documento formattato in html. L’accesso al database è ottenuto
attraverso l’utilizzo di ODBC.
Bisogna tenere presente che ODBC lavora con una connessione diretta mentre Internet è una rete a
pacchetti senza connessione (connection less): un browser si appoggia ad un web server il tempo
necessario per scaricare un file, mentre Active Server rimane in contatto il tempo necessario per
effettuare due compiti:
connettersi al database e produrre un recordset;
abilitare l’applicazione ad effettuare successive chiamate e ad accedere ai dati
precedentemente ritrovati.
OLE DB accedono ai dati in maniera diretta e molto più rapidamente di DAO o RDO che invece
passano attraverso il livello ODBC.
ADO usa un linguaggio di alto livello appoggiandosi direttamente sulle OLE DB che sono di più
basso livello. In tal modo possiamo utilizzare ADO per accedere al database.
ADO sono solo una possibile implementazione dei ActiveX Component per accedere al database,
usando un qualsiasi linguaggio possiamo costruire component personalizzati conformi alle specifiche
del COM.
ADO lavora meglio delle tecniche tradizionali che usano Data Access Object (DAO) o Remote Data
Object (RDO) per accedere al database specialmente in tutti quei casi dove non abbiamo una
connessione orientata come in Internet. ADO può trattare efficacemente le transizioni verso il database
usando appositi metodi BeginTrans, CommitTrans, Rollback Trans.
ADO è composto essenzialmente da tre oggetti primari: Connection Object, Command Object,
RecordSet Object:
Connection Object è responsabile di raccogliere tutte le informazioni necessarie alla creazione
del RecordSet;
Command Object fornisce un secondo metodo per creare un RecordSet, ed è stato esplicitamente
progettato per passare i parametri alle stored procedure;
RecordSet fornisce la struttura atta a contenere i dati e i metodi necessari per accedere ai dati
presenti nel RecordSet, tutte le funzionalità dei cursori sono rappresentati nell’interfaccia del
RecordSet.
Di seguito è riportato un esempio per costruire un RecordSet:
/* Creo un’istanza del component e lo assegno Obj */
Set Obj = Server.CreateObject("ADODB.Connection")
/* Apertura connessione al database */
Obj.Open ("nameOfIstanza")
/* Impostazione interrogazione */
SQLQuery = " SELECT * from Table "
/* Il risultato della selezione viene posto in un RecordSet, la cui struttura è determinata
dall’impostazione della selezione */
Set ObjRst = Obj.Execute (SQLQuery)
I vantaggi di ADO risiedono nella abilità di riuscire a lavorare in ambienti senza stato, in tutti quei
casi dove il server non ha memoria, non tiene traccia, delle richieste che ha servito e che sono
pervenute dai vari client.
ADO permette di creare robuste applicazioni client/server verso database in modo che più persone
possono accedere contemporaneamente alla stessa base dati nello stesso istante.
Microsoft metterà a punto dei servizi per rendere più agevole il coordinamento delle transizioni.
Poiché il servizio transazionale deve essere in grado di interagire con altri sistemi transazionali
eterogenei, Microsoft ha realizzato un’architettura capace non solo di integrarsi perfettamente in
Internet ma anche di interoperare con sistemi transazionali già esistenti.
Immaginiamo di avere il nostro file CINETECA.MDB che contiene informazioni relative alle
videocassette di una videonoleggio. Soffermiamoci su due tabelle di cui riportiamo la struttura:
Tabella ATTORI_REGISTI:
Nome
datoIDInteroNOMETestoCOGNOMETestoDATA_NASCITADataDATA_SCOMPDataNAZIONETesto
campoTipo
Tabella FILM:
Nome campoTipo datoIDInteroTITOLOTestoID_REGISTAInteroANNODataQUANTITAInteroID_ATTOREIntero
Per semplicità abbiamo supposto di riportare un solo attore e un solo regista per ogni film. Un attore
può essere anche regista e viceversa, ecco perché una sola tabella ATTORI_REGISTI con doppia
relazione con la tabella FILM.
La nostra pagina ASP dovrà visualizzare l’elenco completo dei film disponibili nella videoteca, e
quindi con quantità in magazzino maggiore di zero, con nomi e cognomi di attori e registi.
La query SQL che faremo su queste tabelle sarà:
SELECT FILM.*, Attori.COGNOME as attore_Cogn, Attori.NOME as attore_Nome, Registi.COGNOME as
regista_Cogn, Registi.NOME as regista_Nome
FROM FILM, ATTORI_REGISTI Attori, ATTORI_REGISTI Registi
WHERE
Attori.ID=FILM.ID_ATTORE AND Registi.ID=FILM.ID_REGISTA AND
FILM.QUANTITA>0;
Dal Pannello di Controllo di Windows lanciamo dunque l’ODBC Manager (Origini Dati ODBC) e
selezioniamo la voce DSN di sistema. A questo punto possiamo aggiungere in nostro DSN di tipo
Microsoft Access Driver (*.mdb), selezionando il file cineteca.mdb e dandogli il nome che vogliamo,
ad esempio VIDEO. Ora possiamo scrivere il codice VBScript della nostra pagina ASP.
Per prima cosa occorre creare l’oggetto ADODB.Connection:
<% set myConn = Server.CreateObject("ADODB.Connection") %>
dopodiché occorrerà collegarlo al DSN:
<% myConn.Open "VIDEO" %>
Adesso ci serve preparare la stringa con l’istruzione SQL che esegue la query:
<% SQLString = "SELECT FILM.*, Attori.COGNOME as attore_Cogn, "
SQLString = SQLString & "Attori.NOME as attore_Nome, "
SQLString = SQLString & "Registi.COGNOME as regista_Cogn, Registi.NOME "
SQLString = SQLString & "as regista_Nome FROM FILM, ATTORI_REGISTI "
SQLString = SQLString & "Attori, ATTORI_REGISTI Registi WHERE "
SQLString = SQLString & "Attori.ID=FILM.ID_ATTORE AND "
SQLString = SQLString & "Registi.ID=FILM.ID_REGISTA AND "
SQLString = SQLString & "FILM.QUANTITA>0;"
%>
Possiamo ora eseguire l’istruzione conservando i dati di output in una struttura dati apposita:
<% set rsElenco = myConn.Execute(SQLString) %>
Recordset
Come si vede in queste ultime due istruzioni, il metodo Execute della classe Connection restituisce
un oggetto di tipo Recordset. Un Recordset è come una collezione di record ed è quindi composta di
righe (i record) e colonne (i campi).
Per muoversi da un record al successivo del Recordset è necessario invocare il metodo MoveNext,
mentre per leggere il valore di un campo del record si deve utilizzare la sintassi
Recordset("nome_campo")
Noi vogliamo visualizzare una tabella HTML con il risultato della query. Quindi per prima cosa
scriviamo il codice HTML per disegnare l’intestazione della tabella.
<TABLE CELLPADDING=1 CELLSPACING=0 BORDER=1 WIDTH=90%>
<TR>
<TH BGCOLOR=GREEN>
TITOLO
</TH>
<TH BGCOLOR=GREEN>
REGISTA
</TH>
<TH BGCOLOR=GREEN>
ATTORE
</TH>
<TH BGCOLOR=GREEN>
ANNO
</TH>
</TR>
<!-Inserire codice ASP di popolazione tabella à
</TABLE>
Tale codice equivale a disegnare una tabella con la sola intestazione, senza dati:
TITOLOREGISTAATTOREANNO
Ora inseriamo, in luogo del commento, il codice VBScript per la scritture delle righe della tabella:
<% while (rsElenco.EOF<>True) %>
<TR>
<TD>
<%=rsElenco("TITOLO")%>
</TD>
<TD>
<%=rsElenco("regista_Nome")%>   <%=rsElenco("regista_Cogn")%>
</TD>
<TD>
<%=rsElenco("attore_Nome")%>   <%=rsElenco("attore_Cogn")%>
</TD>
<TD>
<%=rsElenco("ANNO")%>
</TD>
</TR>
<% rsElenco.MoveNext
wend
%>
Ora avremo la nostra visualizzazione. Non dimentichiamoci, però, di chiudere e distruggere gli
oggetti Connection e Recordset che altrimenti resterebbero in memoria:
<% set rsElenco = Nothing set myConn = Nothing %>
L’effetto finale sarà del tipo seguente:
TITOLOREGISTAATTOREANNOLa dolce vitaFederico FelliniMarcello Mastroianni1958C’era
una volta in AmericaSergio LeoneRobert De Niro1982Harry a pezziWoody AllenWoody Allen1998
E’ ovviamente possibile inserire dati in un database remoto attraverso, per esempio una form, come
esemplificato più avanti.
PAGINA PER L'INVIO DEI DATI
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>INSERIMENTO DI DATI IN UN DATABASE</title>
</head>
<body style="font-family: verdana; font-size: 10pt">
<h2 align="center">INSERIMENTO DI DATI IN UN DATABASE</h2>
<p>Questo esempio consente di inserire i dati un database.</p>
<form method="POST" action="Inserimento1b.asp">
<p>Nome: <input type="text" name="nome" size="20"></p>
<p>Cognome: <input type="text" name="cognome" size="20"></p>
<p>Email: <input type="text" name="email" size="20"></p>
<p><input type="submit" value="Salva i dati nel database"></p>
</form>
</body>
</html>
PAGINA PER IL SALVATAGGIO DEI DATI
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>INSERIMENTO DI DATI IN UN DATABASE</title>
</head>
<body style="font-family: verdana; font-size: 10pt">
<h2 align="center">INSERIMENTO DI DATI IN UN DATABASE</h2>
<p>Questo esempio consente di inserire i dati un database.</p>
<%
on error resume next
nome = Request.form("nome")
cognome = Request.form("cognome")
email = Request.form("email")
dim conn
dim rs
set conn = Server.CreateObject("ADODB.Connection")
set rs = Server.CreateObject("ADODB.Recordset")
conn.Open "tutorial", "", ""
SQL = "INSERT INTO insertData (nome, cognome, email) "
SQL = SQL & "VALUES ('" & nome & "','" & cognome & "','" & email & "')"
rs.Open SQL, conn
If err.number>0 then
response.write "<p>¼ - Attenzione, hai commesso un errore nello script, controlla e riprova.</P>"
elseif conn.errors.count> 0 then
response.write "<p>Attenzione!</P>"
response.write "<p>I dati inseriti non sono corretti, controllare se i campi obbligatori sono stati
compilati.</P>"
Else
response.write "<p>Ok, i dati sono stati inseriti correttamente!!!!</p>"
End if
conn.Close
%>
<hr>
<p>
<%
Response.Write("<a href="""&Request.ServerVariables("HTTP_REFERER")&""">Torna alla
pagina precedente</a>")
%>
</p>
</body>
</html>