Ricominciamo subito con un argomento piuttosto tosto:
ADO.NET. ADO.NET è accessibile da .NET attraverso il namespace
System.Data. Ogni qualvolta vorremo utilizzare funzioni proprie
di ADO.NET, sarà bene quindi scrivere nel codice:
using System.Data;
ADO.NET ci permette di gestire database SQL Server, Oracle, Access e così
via. Ci permette di creare database, tabelle, campi, foreign-key, primary-key,
constraint tutto in memoria, attuando così quello che
viene definito da Microsoft come accesso ai dati disconnesso.
Cosa significa? In breve:
- Apro la connessione verso il database
- Carico una parte dei dati in memoria
- Chiudo la connessione verso il database (liberando le
risorse)
- Elaboro i dati caricati (che sono in memoria,
ricordiamolo):
aggiungo/cancello/modifico record, apporto tutte le modifiche necessarie,
mantenendo la consistenza logica delle informazioni che dovranno poi essere
riportare sul database fisico (SQL Server, Oracle, Access, MySQL, etc.)
- Al momento del salvataggio, riapro la connessione al
database
- Utilizzo metodi opportuni di ADO.NET per salvare
quello che ho in memoria sul database
- Richiudo la connessione
Questi sono bene o male i passaggi da seguire per avere
a che fare con ADO.NET in modo disconnesso. Il passaggio 4 si sviluppa
tutto in memoria.
Ho volutamente utilizzato in linguaggio semplice e
non molto tecnico proprio per evidenziare come siano cambiate le cose rispetto a
chi (come me) usava Visual Basic 6.0. Non solo: molto spesso parlo con
sviluppatori che fanno fatica ancora oggi a capire
questa logica disconnessa dei dati ed insistono e salvare le
informazioni sul database con le buone vecchie INSERT INTO,
UPDATE, DELETE FROM e così via. Badate bene: sotto sotto, anche ADO.NET utilizza SQL, ovviamente, ma è
reso più trasparente per lo sviluppatore. Trasparente, sia chiaro, non vuol dire
"meno controllo", anzi: io ho programmato quasi una decina d'anni con
Visual Basic 6.0, credevo di avere il pieno controllo, ma con .NET il limite
è stato superato al punto che io probabilmente lo uso al 25%.
Comunque sia, vediamo, prima di scrivere codice, di fare luce su un punto che mi sta a cuore.
Dipendentemente dal database che uso, devo scrivere del codice piuttosto che un altro. Fino
ad un certo punto. La parte coinvolta è quella relativa al caricamento dal
database. In questa fase, per esempio, devo aprire la connessione al database (System.Data.SqlClient.SqlConnection
o System.Data.OleDb.OleDbConnection, per esempio)
e leggerne i dati (System.Data.SqlClient.SqlDataAdapter
o System.Data.OleDb.OleDbDataAdapter).
Piccolo esempio tratto direttamente da MSDN:
public void InsertRow(string myConnectionString)
{
// If the connection string is null, use a default.
if(myConnectionString == "")
{
myConnectionString = "Initial Catalog=Northwind;Data Source=localhost;Integrated Security=SSPI;";
}
SqlConnection myConnection = new SqlConnection(myConnectionString);
string myInsertQuery = "INSERT INTO Customers (CustomerID, CompanyName) Values('NWIND', 'Northwind Traders')";
SqlCommand myCommand = new SqlCommand(myInsertQuery);
myCommand.Connection = myConnection;
myConnection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
}
Non guardate il significato del codice in sè: si
tratta di una function InsertRow() che non fa altro che fare
una INSERT INTO dentro la tabella Customers di Northwind. Notate l'uso di
SqlConnection: questo codice funziona solo con il database di
Northwind sotto SQL Server. Se cambiate la myConnectionString per tentare la
connessione ad Access, otterrete un'eccezione, perchè la classe SQLConnection si
aspetta di potersi connettere solo ad un db SQL Server. Se volessi scrivere la
stessa cosa per Access, dovremo fare un'altra function che utilizzi però
OleDbConnection
.
Tutto il resto
(aggiunta di record, per esempio) invece
utilizza classi indipendenti dal database, proprio perchè, lo
ripeto, lavorano in memoria RAM e sono del tutto
sconnessi rispetto alla base dati da cui provengono. Nel codice che scriveremo, lo vedremo insieme, sembrerà di
avere a che fare con matrici di dati, nonostante .NET ci venga incontro
usando classi dal nome auto-esplicativo.
In questa prima fase nella nostra applicazione
Age
non useremo un database fisico, ma salveremo e leggeremo
files XML: vedremo però che avremo a che fare comunque con classi (DataTable,
DataRow, DataColumn, etc.) il cui significato è strettamente riconducibile ai
database. Lo ripeto per l'ennesima volta: scriveremo in .NET del codice che
creerà in memoria la
struttura logica di un vero e proprio database, con tabelle, campi, e volendo
relazioni fra tabelle, chiave esterne, primary-key, etc. etc.
Quello che secondo me è il vero fulcro di
ADO.NET: la classe DataSet
Io personalmente considero la classe
DataSet il vero fulcro di ADO.NET, per almeno un paio di
motivi:
- è l'oggetto che sta a metà strada tra mondo
disconnesso e mondo connesso. Lavorando con la classe
xxxDataAdapter (dove 'xxx' è OleDb oppure
Sql), il DataSet si riempie con i dati provenienti dal
database (punto 2 dell'elenco sopra)
- il DataSet è la rappresentazione vera e propria
di un database in memoria. La property Tables contiene la
collection con tutte le tabelle (classe DataTable) che
abbiamo caricato nel DataSet. I metodi GetXML, GetXMLSchema, ReadXML e ReadXMLSchema generano e
leggono files XML contenenti la struttura e i dati del DataSet. Altri membri
importanti della classe DataSet sono: Copy, Merge, HasChanges, HasErrors.
Un po' di teoria, seppur noiosa, ci voleva,
giusto? Ho pensato fosse importante, per me e per voi rivedere velocemente
i concetti base che stanno dietro ad ADO.NET. Ho trovato ancora molto più
importante ribadire per l'ennesima volta che l'approccio di ADO.NET è
quello disconnesso: possiamo tranquillamente dire
che gran parte parte della rivoluzione che Microsoft ha attuato con
ADO.NET riguarda proprio questa nuova logica, questo nuovo modo di intendere
l'elaborazione delle informazioni nel caso in cui (non l'abbiamo ancora detto)
non abbiamo sempre a disposizione la base dati (palmari, applicazioni web,
etc.)
Nel prossimo post, finalmente, vedremo come usare
ADO.NET per creare il nostro piccolo DataSet, come (salvarlo su | caricarlo da)
file XML. Non so se ci avete fatto caso, ma adesso ogni volta che si lancia
Age la nostra ListBox appare vuota. E' ora di farla finita! Se
inserisco 10 compleanni, quelli di qualche amico o quelli della mia famiglia, li
voglio salvare e li voglio recuperare subito, che ne dite?