|
ASP: la guida introduttiva
Capitolo 9 - ASP e database
9.0 Introduzione
9.1 Primo
approccio ad ADO
9.2 Metodi e
proprietà di Connection
9.3 Il metodo
Execute e le istruzioni SQL
9.4 Approccio
agli oggetti Recordset
9.0 - Introduzione
Uno
delle peculiarità che ha portato ASP ad una vasta diffusione
consiste nella facilità con la quale è possibile interfacciare
uno script ad una fonte di dati che rispetti lo standard detto
ODBC (Open Database Connectivity). La
connettività verso fonti di dati ODBC permette di realizzare con
il minimo sforzo un innumerevole quantitativo di applicazioni,
che spazia dal semplice guestbook fino ad arrivare a potenti
interfacce di ricerca su cataloghi online. In pratica grazie ai
database diventa semplice la catalogazione di lunghe moli di
dati e facile l'accesso ad essi grazie all'oggetto
ActiveX Data Object (abbreviato ADO),
che fornisce connettività verso tutti i tipi di database che
supportino ODBC, mediante un driver apposito. In ASP, a livello
elementare, è praticamente prassi l'utilizzo dei database di
Access, non a caso prodotto sempre da Microsoft. Per addentrarsi
nello studio della connettività verso fonti di dati ODBC non è
ora richiesto alcun prerequisito particolare, anche se magari
una praticità già acquisita con i database manager e con SQL
potranno certamente aiutare nella comprensione dei paragrafi e
dei capitoli successivi dedicati all'argomento. Tutti gli esempi
riportati in questa sede si baseranno, per amore dello standard
di ASP, sui database di Access. Sarà dunque necessario disporre
di una versione abbastanza recente di questo (97 o
preferibilmente 2000) per procedere.
9.1 - Primo approccio ad ADO
Come
appena detto ADO è il tramite necessario per operare, sia in
lettura che in scrittura, su una fonte di dati ODBC. Il primo
oggetto che si incontra analizzando questo componente è
Connection, che, come il nome lascia
ad intuire, si occupa di fornire la connettività verso un
database. L'oggetto Connection va dichiarato come un qualsiasi
ActiveX, mediante la seguente sintassi:
var ADOConn = new ActiveXObject("ADODB.Connection");
Tramite il riferimento ADOConn è ora
possibile accedere a metodi e proprietà di tale oggetto.
Prima di procedere oltre, al fine di seguire gli esempi
presentati, è necessario ora realizzare un piccolo database
Access di prova. Si vada ad avviare la propria copia di Access,
si scelga dall'interfaccia iniziale l'operazione di creazione di
un nuovo database vuoto e lo si vada a riporre, con un nome
arbitrario, ad esempio prova.mdb,
nella cartella che ospiterà i codici ASP analizzati di seguito.
Da Access ora si crei una nuova tabella in visualizzazione
struttura ed in essa si vadano ad inserire i seguenti campi:
-
id,
di tipo contatore, da selezionare come chiave primaria
mediante click sull'iconcina a forma di chiave (la riga di
questo record nella visualizzazione struttura deve essere
selezionata mentre si clicca sull'icona)
-
nome,
di tipo testo
-
cognome,
di tipo testo
-
e_mail,
di tipo testo
Chiudendo la finestra di visualizzazione struttura si scelga di
salvare tali aggiunte e si assegni un nome alla tabella appena
creata, ad esempio nominativi.
Tornando alla schermata precedente sarà ora possibile
visualizzare nell'elenco delle tabelle quella appena creata. Si
esegua un doppio click sul suo nome per accedere alla finestra
che permetterà di immettere dati all'interno della tabella. Per
testare gli esempi si generino due rige (record) con dati
arbitrari e fantasiosi, ad esempio Mario Rossi mrossi@tin.it
e Giuseppe Bianchi gbianchi@libero.it. Come è possibile
notare il campo id, che è un contatore nonché la chiave
primaria, si incrementa da solo ad ogni inserimento di record,
generando una relazione univoca tra l'insieme dei record
inseriti e i numeri naturali. A questo punto si salvi tutto e si
chiuda pure Access, il database di esempio è pronto.
Si utilizzi ora in maniera dogmatica il seguente codice, tanto
per vedere in pratica sin dall'inizio il risultato cercato:
<%@ LANGUAGE = JScript %>
<%
// Istanzio l'oggetto Connection
var ADOConn = new ActiveXObject("ADODB.Connection");
// Creo la STRINGA DI CONNESSIONE
var strConn = "";
strConn += "driver={Microsoft Access Driver (*.mdb)};";
strConn += "dbq=" + Server.MapPath("prova.mdb");
// Apro la connessione al database selezionato
ADOConn.Open(strConn);
// Interrogo il database
var sql = "SELECT * FROM nominativi";
var ris = ADOConn.Execute(sql);
// Stampo i dati contenuti nel database
while (!ris.EOF) {
Response.Write("Record n° " + ris("id") + "<br>");
Response.Write("Nome: " + ris("nome") + "<br>");
Response.Write("Cognome: " + ris("cognome") + "<br>");
Response.Write("E mail: " + ris("e_mail") + "<br><br>");
ris.MoveNext();
}
// Chiudo la connessione
ADOConn.Close();
%>
Non
si meravigli il lettore se l'esempio non dovesse risultare da
subito di facile compresione, questo stesso codice servirà ora
come appoggio per analizzare nel dettaglio le diverse fasi
dell'accesso ad un database.
9.2 - Metodi e proprietà di Connection
All'interno dell'esempio di poche righe sopra si è fatto ricorso
a tre distinti metodi dell'oggetto ADODB.Connection:
Open, Execute
e Close. In buona sostanza già questi
soli tre metodi, il cui utilizzo però non è immediato,
permettono l'accesso ad una fonte di dati ODBC. Ad essi si
aggiungono poi altri elementi di interfaccia meno sfruttati, ma
comunque buoni da conoscere. Per questo è presentata anzitutto
una cernita dell'interfaccia base messa a disposizione
dall'oggetto Connection. Si tenga presente che anche in questo
caso non sono riportati né tutti i metodi né tutte le proprietà
dell'oggetto, ma si è scelto scartando i meno utili
nell'apprendimento iniziale dell'argomento. Qualunque
approfondimento può essere svolto documentandosi su
http://www.microsoft.com/data/ado/
|
Metodi |
|
|
|
|
Cancel |
Annulla l'esecuzione di una chiamata dei metodi Execute e
Open in attesa |
|
Close |
Chiude un oggetto aperto e i relativi oggetti dipendenti |
|
Execute |
Esegue la particolare istruzione SQL passata al metodo
mediante un parametro stringa |
|
Open |
Apre una connessione a una fonte dati |
|
|
|
|
Proprietà |
|
|
|
|
ConnectionString |
Contiene le informazioni utilizzate per stabilire una
connessione a una fonte dati |
|
ConnectionTimeout |
Indica in secondi il tempo di attesa da considerare durante
il tentativo di stabilire una connessione prima di terminare
il tentativo e generare un errore |
|
CursorLocation |
Imposta o restituisce la posizione del motore del cursore |
|
Version |
Indica il numero di versione di ADO |
|
|
|
Il
particolare metodo Open si occupa
dell'aprire una connessione verso la fonte di dati specificata
in una stringa, detta stringa di connessione, passata al metodo
sotto forma di parametro. Le stringhe di connessione sono basate
su una particolare sintassi. Ogni stringa di connessione è
costituita da una serie di coppie chiave-valore, separate
tra di loro con un punto e virgola. Le chiavi sono invece
separate dai rispettivi valori mediante il simbolo di uguale.
Nel più tipico dei casi è necessario inserire in tale stringa
almeno due coppie, atte ad indicare il formato di database
utilizzato e la sua locazione fisica nel file system del server.
Ad esempio:
var strConn = "";
strConn += "driver={Microsoft Access Driver (*.mdb)};";
strConn += "dbq=C:\\Inetpub\\wwwroot\\dati\\database.mdb;";
Di
solito il valore associato alla chiave dbq
è ricavato mediante l'utilizzo del metodo Server.MapPath, in
modo da ottenere automaticamente la conversione di un percorso
relativo in un percorso assoluto. Così è stato fatto
nell'esempio precedente.
All'interno della stringa di connessione possono poi essere
specificati ulteriori dati, ad esempio un'opzionale password
associata al database (senza la quale non sarebbe possibile
l'accesso ai dati in esso contenuto), alla seguente maniera:
strConn += "psw=vgh564;";
Una
volta stabilita la stringa di connessione è dunque possibile
avviare l'accesso alla fonte di dati specificata:
ADOConn.Open(strConn);
Da
questo momento in poi sarà possibile dunque operare sul database
specificato attraverso i metodi di Connection e degli oggetti ad
esso collegati. Una volta concluse tutte le operazioni
preventivate è buona norma chiudere la connessione, utilizzando
il metodo Close:
ADOConn.Close();
9.3 - Il metodo Execute e le istruzioni SQL
Tipicamente il fulcro del lavoro viene svolto dal metodo
Execute, a cui è data la possibilità
di eseguire ricerce, effettuare modifiche o cancellare dei
record presenti in una tabella. Tale metodo accetta un parametro
di tipo stringa, contenente un'istruzione SQL da eseguire. In
buona sostanza all'interno di questa stringa viene detto
esplicitamente al metodo Execute cosa fare.
SQL (Structured Query Language, si dovrebbe pronunciare
sequel, ma quasi tutti in Italia dicono esseccuelle)
è un linguaggio che rappresenta lo standard per la definizione,
l'interrogazione e la modifica dei database. Per sfruttare la
connettività ai database fornita da ADO non occorre essere dei
guru di SQL, tuttavia è necessario apprendere la sintassi e
l'uso di base di questo linguaggio. Nonostante un piccolo sforzo
iniziale ci si accorgerà presto di quanto la struttura di SQL
sia facile da apprendere e persino vicina al linguaggio
naturale, e per questo semplice o addirittura piacevole da
sfruttare. Si torni all'ora all'esempio già presentato:
var sql = "SELECT * FROM nominativi";
var ris = ADOConn.Execute(sql);
Si
incotra qui per la prima volta nel corso di questa guida
un'istruzione SQL. Le parole chiave utilizzate sono state
enfatizzate mediante il grassetto. Letteralmente "SELECT * FROM
nominativi" può essere tradotto in "SELEZIONA ogni campo DALLA
TABELLA nominativi". Il metodo Execute, eseguendo questo
comando, restituisce un riferimento ad un oggetto di tipo
Recordset. Come ancora una volta il
nome lascia intuire, un oggetto di tipo Recordset rappresenta
una collezione di record, estratti dal datadase dal metodo
Execute rispettando ciò che è stato domandato dall'istruzione
SQL. In questo caso, infatti, l'oggetto restituito colleziona
tutti i campi di tutti i record presenti nella tabella
nominativi del database. Un diverso
comando SQL avrebbe ritornato un diverso Recordset, ad esempio
eseguendo una selezione basata su qualche particolare regola o
ispezione dei campi di ogni singolo record. Una volta estratti i
dati di proprio interesse dal database, tramite l'utilizzo della
sintassi di SQL e dell'oggetto Connection, è quindi possibile
gestirli attraverso l'interfaccia pubblica dell'oggetto
Recordset. Andando avanti nel corso di questa guida saranno
approfonditi gli aspetti relativi sia ad SQL che all'utilizzo
dei Recordset. Per il momento si è voluto esclusivamente
avvicinare il lettore all'ideologia che permea l'accesso alle
fonti di dati ODBC. Le applicazioni pratiche e l'approfondimento
delle tematiche saranno dunque presentati passo passo da qui in
poi.
9.4 - Approccio agli oggetti Recordset
Il
Recordset ricavato dal codice dell'esempio contiene dunque tutti
i record che costituiscono la tabella nominativi del database
utilizzato. E' ora possibile muoversi all'interno dei dati
acquisiti semplicemente sfruttando i metodi e le proprietà degli
oggetti Recordset, qui presentati in maniera non ufficiale. In
particolar modo, per ottenere una stampa a video di tutti i dati
ricevuti dalla fonte, è stato messo in atto un ciclo
while basato sulla proprietà
EOF e sul metodo
MoveNext di Recordset.
I Recordset possono essere immaginati come vere e proprie
tabelle di dati, dove ogni riga corrisponde ad un record, un po'
come nella rappresentazione visuale di Access. Tale ideologica
tabella può essere letta mediante l'utilizzo di un
cursore. Appena l'oggetto Recordset è
stato creato il cursore è posizionato all'inizio della prima
riga di tale tabella. In questa situazione i singoli campi del
record evidenziato dal cursore sono leggibili tramite l'utilizzo
della sintassi
ris("nome_campo")
ed
infatti si osservi questa porzione estratta dall'esempio:
Response.Write("Record n° " + ris("id") + "<br>");
Response.Write("Nome: " + ris("nome") + "<br>");
Response.Write("Cognome: " + ris("cognome") + "<br>");
Response.Write("E mail: " + ris("e_mail") + "<br><br>");
Il
contenuto dei quattro campi disponibili nella tabella nominativi
viene inviato all'output utilizzando proprio la sintassi di
accesso ai campi appena mostrata. Il cursore può inoltre essere
spostato in avanti lungo i vari record posseduti mediante il
metodo MoveNext(). Una chiamata a tale metodo, insomma, causa
l'avanzamento alla riga successiva dell'ideale tabella dei dati
ricavati dal database. Naturalmente il numero di record che
costituisce un Recordset è per forza di cose finito, e non sarà
possibile spostarsi in avanti su di esso per più di tot volte.
Se si tenta un avanzamento del cursore quando questo ha già
scavalcato l'ultimo record della collezione, infatti, viene
lanciato un errore e l'esecuzione dell'intero script viene
interrotta. E' qui che torna dunque utile il valore booleano
della proprietà EOF dell'oggetto Recordset. EOF è
true solo quando il cursore è
posizionato al termine dell'ultima riga disponibile,
false altrimenti. Inglobando dunque
gli strumenti acquisiti in un ciclo while diventa possibile il
controllo e la scansione del Recordset ricavato,
indipendentemente dalla lunghezza di esso. Il tipo di
interfaccia utilizzato da Recordset è piuttosto diffusa in
diversi ambienti, Java su tutti, ed è semplice da assimilare
proprio per una somiglianza con la naturale maniera di pensare
dell'uomo. La parte conclusiva di questo script, infatti, può
essere così tradotta in linguaggio naturale:
fino a quando non raggiungi la fine della tabella dei
dati {
stampa i dati presenti nella riga attuale;
avanza di una riga;
}
L'interfaccia di Recordset, comunque, non termina qui e quella
esaminata non è che una delle tante pratiche nelle quali è
possibile sfruttare un Recordset. Altre situzioni simili o meno
a questa verranno presentate nel corso dei capitoli successivi.
|