|
Dettagli tecnici
Prima di iniziare, qualche dettaglio tecnico. Per i prossimi esempi userò MySql. Trovate una guida su come scaricarlo, configurarlo
e gestirlo nel capitolo A1 del tutorial dedicato a LINQ. Oltre a ciò che viene descritto in quella
sezione, avremo bisogno di alcune classi per interfacciarci con MySql, e che non sono presenti nell'installazione standard del framework.
Potete scaricare gli assemblies necessari da qui. Essi verranno automaticamente
installati nella GAC e saranno accessibili sucessivamente assieme a tutti gli altri assemblies fondamentali nella scheda ".NET" della finestra
di dialogo "Add Reference", già spiegata precedentemente. Per usarli, importate i riferimenti e aggiungete le direttive Imports
all'inizio del sorgente.
Connessione
La prima cosa da fare per iniziare a smanettare su un database consiste principalmente nel collegarsi alla macchina sulla quale esso esiste,
che possiamo definire server. L'applicazione è quindi un client (vedi capitolo sui Socket), che instaura un collegamento non solo
fisico (tramite Internet), ma anche logico, con il programma che fornisce il servizio di gestione dei database; nel nostro caso si tratta di
MySql. Per gli esempi che userò, l'host, ossia l'elaboratore che ospita il servizio, coinciderà con il vostro stesso computer,
ossia ci connetteremo a localhost (127.0.0.1). Se avete installato tutto senza problemi e avviato MySql correttamente, possiamo iniziare ad
analizzare la prima classe importante: MySqlConnection. Essa fornisce le funzionalità di connessione sopracitate mediante due
semplici metodi: Open (apre la connessione) e Close (la chiude). Il suo costruttore principale accetta come argomento una stringa detta
connection string, la quale definisce dove e come eseguire il collegamento. Tipicamente, è formata da varie parti, separate
da punti e virgola, ciascuna delle quali imposta una data proprietà. Eccone un esempio:
Imports MySql.Data.MySqlClient
'...
'Crea una nuova connessione all'host locale,
'accedendo al servizio come utente "root" e con
'password "root". Se non avete modificato le
'impostazioni di sicurezza, questa coppia di username
'e password è quella predefinita.
'Naturalmente è un'idiozia mantenere queste
'credenziali così ovvie e dovrebbero essere cambiate
'subito, ma per i miei esempi userò sempre root.
Dim Conn As New MySqlConnection("Server=localhost; Uid=root; Pwd=root;")
Try
'Avvia la connessione
Conn.Close()
Catch Ex As Exception
'...
Finally
'E la chiude. Ricordatevi che è sempre bene
'chiudere la connessione anche quando si verifichino
'errori (anzi, soprattutto in queste situazioni).
Conn.Close()
End Try
Esiste anche un'altra variante della connection string, che si presenta come segue:
"Data Source=localhost; UserId=root; PWD=root;"
Una volta connessi, è possibile effettuare operazioni varie sui database, anche se, a dir la verità, noi non abbiamo ancora
nessun database su cui operare...
Esecuzione di una query
Il termine query indica una stringa mediante la quale si interroga un database per ottenerne informazioni, o per creare/modificare quelle
già contenutevi. Le query presentano una loro sintassi particolare, la quale, pur variando leggermente da un gestore all'altro
(MySql, Sql Server, Oracle, Access, eccetera...), aderisce ad uno standard universale: l'SQL, appunto (Structured Query Language).
In questo capitolo e nei prossimi analizzerò solo qualche semplice esempio di query, poiché la trattazione del linguaggio
intero richiederebbe svariati capitoli suppletivi che esulano dalle intenzioni di questa guida. Vi invito, comunque, a scegliere una
guida a questo linguaggio, o almeno un reference manual, da leggere in parallelo con i prossimi capitoli. Alcuni link interessanti:
World Wide Web Consortium, Morpheus Web,
HTML.it (SQL) HTML.it (MySQL).
Per iniziare, vediamo quale classe gestisca le query. Si tratta di MySqlCommand. Essa espone alcuni costruttori, tra cui uno senza
parametri, ma tutti gli argomenti specificabili sono anche accessibili tramite le sue proprietà. I membri significativi sono:
- Cancel() : cancella l'esecuzione di una query in corso;
- CommandText : indica la query stessa;
- CommandTimeout : il tempo massimo, in millisecondi, oltre il quale l'esecuzione della query viene annullata;
- Connection : determina l'oggetto MySqlConnecction mediante il quale si è connessi al database. Senza connessione, ovviamente,
non si potrebbe fare un bel niente;
- ExecuteNonQuery() : esegue la query specificata e restituisce il numero di record da essa affetti, ossia selezionati, creati, cancellati
o modificati. Restituisce -1 in caso di fallimento;
- ExecuteReader() : esegue la query e restituisce un oggetto MySqlDataReader che permette di scorrere una alla volta le righe che sono
state selezionate. Il reader, come suggerisce il nome, "legge" i dati, ma questi sono virtualmente posti su un flusso immaginario,
poiché la query non viene eseguita tutto in un colpo, ma di volta in volta. Vedremo successivamente, più in dettaglio
come usare un oggetto di questo tipo e quali limitazioni comporta;
- ExecuteScalar() : esegue la query e restituisce il contenuto della prima colonna della prima riga di tutti i risultati. Restituisce
Nothing se la query fallisce;
Ora, per prima cosa, dobbiamo creare un nuovo database: potete farlo manualmente da SQL Yog o da qualsiasi altro programma di gestione,
ma io userò solo codice, per evitare di imporre vincoli inutili:
'Potete porre questo sorgente sia
'in una Windows Application sia in una Console Application,
'anche perchè lo useremo solo una volta.
Dim Conn As New MySqlConnection("Server=localhost; Uid=root; Pwd=root;")
Dim Cmd As New MySqlCommand()
Try
Conn.Open()
Cmd.Connection = Conn
'Crea un nuovo database di nome "appdata"
Cmd.CommandText = "CREATE DATABASE appdata;"
Cmd.ExecuteNonQuery()
Catch Ex As Exception
Finally
Conn.Close()
End Try
Quando il nuovo database è creato, possiamo modificare la connection string in modo da aprire quello desiderato: la sintassi per
indicare il database di default è "Database=[nome db];" oppure "Initial Catalog=[nome db];". Per esemplificare questa nuova aggiunta
alla stringa di connessione, utilizziamo anche un codice per creare la tabella su cui lavoreremo:
Dim Conn As New MySqlConnection("Server=localhost; Database=appdata; Uid=root; Pwd=root;")
Dim Cmd As New MySqlCommand()
Try
Conn.Open()
Cmd.Connection = Conn
'Crea una nuova tabella di nome Customers nel database
'appdata. I suoi attributi (colonne) sono:
' - ID : identificativo numerico del record; non può essere
' vuoto, viene autoincrementato quando si aggiunge una
' nuova riga ed è la chiave primaria della
' relazione Customers
' - FirstName : nome del cliente (max 150 caratteri)
' - LastName : cognome del cliente (max 150 caratteri)
' - Address : indirizzo (max 255 caratteri)
' - PhoneNumber : numero telefonico (max 30 caratteri)
Cmd.CommandText = "CREATE TABLE Customers (ID int NOT NULL AUTO_INCREMENT, FirstName char(150), LastName char(150), Address char(255), PhoneNumber char(30), PRIMARY KEY (ID));"
Cmd.ExecuteNonQuery()
Catch Ex As Exception
Finally
Conn.Close()
End Try
Con lo stesso procedimento, è anche possibile inserire tuple nella tabella mediante il "comando" insert into:
INSERT INTO Customers VALUES(1, 'Mario', 'Rossi', 'Via Roma 89, Milano', '50 288 41 971');
Qui potete trovare una cinquantina di queries create a random da eseguire sulla tabella per inserire qualche valore,
giusto per avere un po' di dati su cui lavorare.
Enumerazione di record
Come accennato, precedentemente, quando si esegue ExecuteReader, viene restituito un oggetto MySqlDataReader che permette di scorrere i
risultati di una query. Ecco una breve descrizione dei suoi membri:
- Close() : chiude il reader. Dato che mentre il reader è aperto, nessuna operazione può essere eseguita sul
database, è sempre obbligatorio chiudere l'oggetto dopo l'uso;
- FieldCount : indica il numero di attributi della riga corrente;
- Get...(i) : tutte le funzioni il cui nome inizia per "Get" servono per ottenere il valore della i-esima colonna sottoforma di un
particolare tipo;
- HasRows : determina se il reader contenga almeno un record da leggere;
- IsClosed : indica se l'oggetto è stato chiuso;
- IsDbNull(i) : restituisce True se il campo i-esimo del record corrente non contiene un valore (rappresentato dalla costante DBNull.Value);
- Read() : legge una nuova riga e restituisce True se l'operazione è riuscita. False significa che non c'è più nulla
da leggere;
Ecco un esempio di come usare il Reader, in un'applicazione Windows Form con una listview e un pulsante:
Imports MySql.Data.MySqlClient
Class Form1
Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click
Dim Conn As New MySqlConnection("Server=localhost; Database=appdata; Uid=root; Pwd=root;")
Dim Command As New MySqlCommand
Try
'Seleziona tutti i record della tabella Customers,
'includendovi tutti gli attributi. Questa query è
'equivalente a:
' SELECT ID, FirstName, LastName, Address, PhoneNumber FROM Customers
Command.CommandText = "SELECT * FROM Customers;"
Command.Connection = Conn
Conn.Open()
'Esegue la query e restituisce il reader
Dim Reader As MySqlDataReader = Command.ExecuteReader()
lstRecords.Columns.Clear()
'Aggiunge tante colonne alla listview quanti sono
'gli attributi dei record selezionati. È possibile
'ottenere il nome di ogni colonna con la funzione
'GetName di MySqlDataReader
For I As Int32 = 0 To Reader.FieldCount - 1
lstRecords.Columns.Add(Reader.GetName(I))
Next
Dim L As ListViewItem
Dim S(Reader.FieldCount - 1) As String
'Fintanto che c'è qualche record da leggere,
'lo aggiunge alla listview
Do While Reader.Read()
'Riempie l'array S con i valori degli attributi
'della tupla corrente. Se una cella non contiene
'valori, mette una stringa vuota al suo posto
For I As Int32 = 0 To S.Length - 1
If Not Reader.IsDBNull(I) Then
'GetString(I) ottiene il valore della cella
'I sottoforma di stringa
S(I) = Reader.GetString(I)
Else
S(I) = ""
End If
Next
L = New ListViewItem(S)
lstRecords.Items.Add(L)
Loop
'Chiude il Reader
Reader.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, Me.Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Finally
'Chiude la connessione
Conn.Clone()
End Try
End Sub
End Class

|
|