Il mio precedente post dedicato all'argomento ha suscitato un piccolo dibattito, cosa che mi fa molto piacere
. Come promesso, oggi parlerò di LINQ to SQL Desisgner, che consente di creare il DAL utilizzato da LINQ in maniera completamente visuale. Per accedere a questo strumento, bisogna aggiungere al progetto un elemento di tipo LINQ to SQL File. Supponiamo di chiamarlo Database. Nel progetto viene inserito un file di nome Database.dbml con due file collegati, ovvero Database.dbml.diagram e Database.dbml.cs (nel caso si stia utilizzando C#). In realtà ci si può dimenticare dell'esistenza di questi file, perché da ora in poi il DAL sarà creato tramite Drag & Drop, utilizzando la finestra delle Proprietà per modificarne le impostazioni.
E' sufficiente selezionare un database nel Server Explorer, quindi trascinare le tabelle desiderate all'interno del designer. Se esistono relazioni di chiave esterna tra di esse, verranno automaticamente aggiunte al diagramma. Ad esempio, consideriamo due tabelle di nome Users e Cities, legate dalla chiave CityID; ecco come appaiono dopo averle inserite nel LINQ to SQL Designer:
Dietro le quinte viene generato il codice che consente di accedere al database utilizzando LINQ. Il layer prodotto si occupa anche di effettuare automaticamente le eventuali giunzioni tra le tabelle, cosicché da un oggetto di tipo User è possibile accedere ai valori del record City corrispondente, senza dover indicare il join in modo esplicito. Come sempre un esempio vale più di mille parole:
1 using (DatabaseDataContext db = new DatabaseDataContext())
2 {
3 var query = from user in db.Users orderby user.UserName select user;
4 foreach (var record in query)
5 MessageBox.Show(record.UserName + " - " + record.City.CityName);
6 }
La query alla riga 3 recupera tutti gli utenti, ordinandoli per nome. Il ciclo successivo li visualizza con la relativa città. La proprietà City dell'oggetto record viene riempita automaticamente, in base alla relazione esistente tra le due tabelle (User.CityID = City.CityID).
Uno dei motivi per cui è nato LINQ è quello di fornire un modello unificato di accesso alle fonti dati, siano esse oggetti, file XML oppure database relazionali. Proprio da questi ultimi ho cominciato i miei "esprimenti". Vediamo prima la strada più lunga... Il .NET Framework 3.5 mette a disposizione un tool a riga di comando, SQLMetal.exe, che consente di creare un file di mapping, in C# oppure VB .NET, con cui accedere ad un database SQL senza doversi preoccupare di stringhe di connessione, oggetti Command e Parameter... In una parola sola: DAL
. In Orcas Beta 1 questo programma è contenuto nella cartella C:\Program Files\Microsoft Visual Studio 9.0\SDK\v3.5\Bin.
Supponiamo di avere su SQL Server 2005 un database di nome SitesDB con al suo interno una tabella Sites così definita:
CREATE TABLE Sites (
ID int IDENTITY(1,1) NOT NULL,
Url nvarchar(255) NOT NULL,
LastCheck datetime NULL,
Enabled bit NOT NULL)
Eseguendo il tool SQLMetal.exe su tale database si ottiene un file di mapping che deve essere aggiunto al proprio progetto .NET. Fatto questo, bastano pochissime righe di codice per accedere al database con LINQ, leggere i valori in esso contenuti e fare delle modifiche. Ad esempio:
1 using (SitesDB db = new SitesDB(Settings.Default.SQLConnectionString))
2 {
3 using(WebClient wc = new WebClient())
4 {
5 var query = from site in db.Sites where site.Enabled select site;
6 foreach (var record in query)
7 {
8 try
9 {
10 wc.DownloadString(record.Url);
11 //Il sito è accessibile. Aggiorna la data di validità.
12 record.LastCheck = DateTime.Now;
13 }
14 catch (Exception)
15 { }
16 }
17 }
18 //Invia le modifiche al database.
19 db.SubmitChanges();
20 }
La riga 5 recupera tutti i record della tabella Sites il cui attributo Enabled vale true. Dopo aver modificato il valore di LastCheck, se necessario (riga 12) l'istruzione db.SubmitChanges() alla riga 19 riporta tutte le modifiche nella base di dati.
E' interessante notare una cosa. L'istruzione alla riga 5 non lancia effettivamente la query sul database: la sua esecuzione avviene solo nel momento in cui si effettua il primo accesso ai dati (in questo caso, il ciclo foreach alla riga 6).
Questo è solo un primo assaggio delle potenzialità che LINQ offre per l'accesso ai database relazionali. Nei prossimi giorni mostrerò altre caratteristiche, a cominciare dal LINQ to SQL Designer, lo strumento che consente di creare il mapping tra database e LINQ in maniera completamente visuale. Di esso mi occuperò nel prossimo post, quindi... Stay tuned
.