LINQ mi piace
31 Dicembre 2007
Devo dire che all’inizio LINQ in C# mi lasciava un po’ perplesso. L’idea di complicare il linguaggio di programmazione aggiungendo costrutti mi rende nervoso. Io la chiamo sindrome da PL/I ma l’ho sperimentata con il C++: il linguaggio diviene così complesso che per realizzare un progetto serve un esperto del linguaggio stesso.
LINQ in realtà si integra bene con C# e diviene presto naturale utilizzarlo. Per provarlo ho aggiunto delle funzioni di ricerca relativamente sofisticate ad un mio programma (in realtà è il mio Pet Project che uso per fare esperimenti) utilizzando il binding SQL.
Ho creato un piccolo parser utilizzando una serie di if con una serie di espressioni regolari. Ho cablato diverse query utilizzando i risultati di questo piccolo parser. In pratica prelevo il contenuto del TextBox di ricerca e quando soddisfa il match con una espressione regolare simile a questa (ho semplificato il codice)
Regex reAnnoMese = new Regex(@"^([0-9]){4}\s+[a-zA-Z]+$");
eseguo la query corrispondente simile a questa
if (reAnnoMese.Match(searchText).Success) { RicevutaDataContext dcRicevuta = new RicevutaDataContext(); int posSpazio = searchText.IndexOf(" "); string anno = searchText.Substring(0, posSpazio); string mese = searchText.Substring(posSpazio + 1); int numeroMese = GetMonthNumber(mese); var queryRicevuta = from ricevuta in dcRicevuta.Ricevutas orderby ricevuta.Anno descending, ricevuta.Numero descending where ricevuta.Anno.Equals(anno) && ricevuta.DataEmissione.Value.Month == numeroMese select ricevuta; DataContext = queryRicevuta; }
RicevutaDataContext è un DataContext creato con un semplice drag&drop della tabella Ricevuta dal mappatore del VS2008. GetMonthNumber è una funzione che restituisce il numero ordinale corrispondente al mese e utilizza al suo interno le funzioni .NET per la localizzazione e che restituiscono i nomi dei mesi. Nell’ultima istruzione effettuo il binding della query con un elemento WPF (una Page contenente una ListView in questo caso).
Se nel TextBox scrivete 2006 giugno (o June: dipende dalle impostazioni) questo codice estrae tutte le ricevute emesse nel giugno 2006. LINQ genere codice SQL del tipo:
SELECT [t0].[IdRicevuta], [t0].[Numero], [t0].[Anno], [t0].[DataEmissione], [t0].[Intestazione], .... FROM [dbo].[Ricevuta] AS [t0] WHERE ([t0].[Anno] = @p0) AND (DATEPART(Month, [t0].[DataEmissione]) = @p1) ORDER BY [t0].[Anno] DESC, [t0].[Numero] DESC
Il fatto che il risultato della query LINQ non sia altro che una collezione .NET (per la precisione un IEnumerable su cui è possibile navigare) ne rende l’utilizzo praticamente trasparente.
Il codice non è particolarmente furbo (e neanche elegante) ma è proprio questa la sua bellezza: l’ho scritto senza pensarci troppo e ho ottenuto un buon risultato. Altri meccanismi mi avrebbero costretto a ragionare troppo (Ehi, sono quasi in vacanza!), ad utilizzare classi più complesse, a passare per sofisticati ORM, a scrivere SQL.