Corso .NET - LINQ

  • 1,490 views
Uploaded on

Corso di .NET realizzato dal Dr. Paolo Casoto. Slide relative alla lezione su LINQ, l'ambiente innovativo per l'interazione con i dati in ambitne .NET

Corso di .NET realizzato dal Dr. Paolo Casoto. Slide relative alla lezione su LINQ, l'ambiente innovativo per l'interazione con i dati in ambitne .NET

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
1,490
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
0
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. + LINQ Il linguaggio universale per la manipolazione di dati in ambiente .NET Dr. Paolo Casoto, Ph.D. - 2012 1
  • 2. + 2 LINQ  LINQ è stato introdotto per la prima volta in .NET 3.5 al fine di garantire un accesso simmetrico e fortemente tipato a differenti tipologie di sorgenti dati  Array, file XML, database relazionali, collezioni di oggetti residenti in memoria  Accedere a tutte le tipologie di dato in modo similare ed interoperabile  Al variare della sorgente dati il codice di accesso può rimanere invariato. Dr. Paolo Casoto, Ph.D. - 2012
  • 3. + 3 LINQ  Formalmente è un linguaggio di query fortemente tipato.  Le query sono molti simili per impostazione a quelle utilizzate in SQL  Di immediata comprensione per la maggior parte dei programmatori  Applicabile anche a quei tipi di dato che hanno poco a che vedere con SQL Dr. Paolo Casoto, Ph.D. - 2012
  • 4. + 4 LINQ ed i costrutti del linguaggio  Per consentire la corretta introduzione di LINQ in .NET 3.5 sono stati aggiunte 5 caratteristiche innovative:  Variabili locali tipizzate in modo implicito;  Sintassi di inizializzazione di collezioni ed oggetti;  Espressioni lambda;  Estensione dei metodi;  Tipi anonimi Dr. Paolo Casoto, Ph.D. - 2012
  • 5. + 5 Variabili locali tipizzate in modo implicito  C# consente di definire una variabile mediante la parola riservata var senza la necessità di definirne il tipo in fase di dichiarazione.  La variabile conserva tuttavia la sua tipizzazione, che viene caratterizzata dal compilatore alla prima inizializzazione della stessa.  Utile in LINQ per gestire il risultato di query il cui tipo di ritorno non può essere definito fino al tempo di compilazione. Dr. Paolo Casoto, Ph.D. - 2012
  • 6. + 6 Sintassi di inizializzazione di collezioni ed oggetti  Caratteristica di .NET nata per gestire la tradizionale tendenza all’esplosione del numero di costruttori delle classi.  In fase di costruzione posso utilizzare il costruttore di default e definire dinamicamente quali attributi inizializzare  Non è altro che una tecnica per ridurre il numero di righe necessarie alla inizializzazione. Dr. Paolo Casoto, Ph.D. - 2012
  • 7. + 7 Esempio  1. var finalPoint;  2. finalPoint = new Point { X = 30, Y = 30 };  La prima riga definisce una variabile generica il cui tipo è determinato alla prima allocazione nella riga due.  La seconda riga invoca per il costruttore di default.  Le due tecniche mi consentono esclusivamente di risparmiare tempo in fase di scrittura del codice. Dr. Paolo Casoto, Ph.D. - 2012
  • 8. + 8 Espressioni Lambda  L’operatore => consente di definire una espressione lambda  Da utilizzare all’interno di un metodo che richiede un delegato fortemente tipato come argomento.  Definizione di un metodo anonimo, senza nome, all’interno di un altro blocco di codice  In particolare per la definizione dei delegati da utilizzare per le operazioni di filtraggio dei dati presenti all’interno delle strutture dati utilizzate da LINQ Dr. Paolo Casoto, Ph.D. - 2012
  • 9. + 9 Esempio static void LambdaExpressionSyntax() { // Make a list of integers. List<int> list = new List<int>(); list.AddRange(new int[] { 20, 1, 4, 8, 9, 44 }); // C# lambda expression. List<int> evenNumbers = list.FindAll(i => (i % 2) == 0); } Espressione LAMBDA: definisco al volo il delegato necessario al metodo FindAll Dr. Paolo Casoto, Ph.D. - 2012
  • 10. + 10 Estensione dei metodi  Estende le funzionalità di una classe, in termini di metodi, senza richiedere l’eredità della classe stessa.  Ad esempio necessario nel caso di gerarchie basate su classi sealed.  Aggiunge funzionalità ad una classe senza richiederne la ricompilazione public static void FunzionalitàAggiuntiva(this object obj) { Console.WriteLine(“Metodo Aggiuntivo”); } Utilizzo il this per indicare il tipo al quale agganciare il nuovo Dr. Paolo Casoto, Ph.D. - 2012 metodo STATICO
  • 11. + 11 Tipi anonimi  TDA privi di una definizione, bensì generati al volo  var purchaseItem = new {  TimeBought = DateTime.Now,  ItemBought = new {Color = "Red", Make = "Saab", CurrentSpeed = 55}, Price = 34.000};  Definisco al volo come dovrà essere strutturato l’oggetto.  Da utilizzare soprattutto per la generazione di oggetti temporanei in fase di definizione delle query di accesso ai dati  E.g.: dati temporanei Dr. Paolo Casoto, Ph.D. - 2012
  • 12. + 12 Perché utilizzare LINQ ?  In ciascuna tipologia di prodotto software parte del tempo di sviluppo è espressamente dedicato alla manipolazione di dati.  Tentativo di realizzare un “lingua franca” per la gestione dei dati, indipendente dallo specifico formato del dato.  Alcuni esempi: LINQ to Objects, LINQ to XML, LINQ to DataSets  Il vantaggio rispetto a SQL: le query LINQ sono tipate !!! Dr. Paolo Casoto, Ph.D. - 2012
  • 13. + 13 Utilizzare LINQ  Tutti i progetti Visual Studio con .NET 3.5 o successivi hanno per default fra i loro riferimenti quello all’assembly System.Core.dll  Le classi per default utilizzano il namespace using System.Linq per incorporare le funzionalità di LINQ  Eventuali assembly di supporto sono necessari per LINQ to XML e LINQ to DataSets Dr. Paolo Casoto, Ph.D. - 2012
  • 14. + 14 Un esempio semplice: gli array  Abbiamo all’interno di un nostro metodo un array di stringhe “pippo”  Vogliamo stampare a video un sottoinsieme di “pippo” costituito dalle sole stringhe che contengono al loro interno il carattere “&”  String[] pippo = {“Bianca&Bearnie”, “You&Me”, “Paolo”}; Dr. Paolo Casoto, Ph.D. - 2012
  • 15. + 15 Un esempio semplice: gli array  Usiamo LINQ per ottenere il sottoinsieme dell’array di nostro interesse  IEnumerable<string> risultati= from p in pippo where p.Contains("&") orderby p select p;  Ottiene una struttura dati ad accesso sequenziale contenente i soli elementi dell’array con al loro interno il carattere “&”  Posso utilizzare i dati, ad esempio, all’interno di un ciclo foreach di stampa.  Proprio perché quello che otteniamo è un generico oggetto iterabile Dr. Paolo Casoto, Ph.D. - 2012
  • 16. + 16 LINQ in linguaggio naturale  Fra gli oggetti p nella From p in pippo collezione pippo …  filtra quelli che contengono “&”… Where p.contains(“&”)  ordinali …  e restituiscili così come sono Orderby p Select p L’ORDINE DELLE CLAUSOLE E’ DIFFERENTE DA QUELLO SQL !!! Dr. Paolo Casoto, Ph.D. - 2012
  • 17. + 17 LINQ e le variabili tipizzate in modo implicito  L’esecuzione di una query LINQ può essere ulteriormente semplificata grazie all’utilizzo delle variabili tipizzate in modo implicito.  var risultati = from p in pippo where p.Contains(" &") orderby p select p;  E’ buona norma utilizzare sempre variabili tipizzate in modo implicito, per ovviare alla gestione dei tipi di ritorno di LINQ.  Anche all’interno del ciclo foreach può essere utilizzata la medesima tecnica. Dr. Paolo Casoto, Ph.D. - 2012
  • 18. + 18 LINQ e l’estensione dei metodi  Grazie all’estensione dei metodi molteplici strutture dati pre- esistenti sono state arricchite di metodo propri di LINQ per consentire l’enumerazione in modo trasparente  E.g.: utilizzato per estendere la classe Array con metodi della interfaccia IEnumerable<T> che non implementa nella sua definizione. Dr. Paolo Casoto, Ph.D. - 2012
  • 19. + 19 Esecuzione delle query LINQ  E’ importantissimo notare come una query LINQ non sia eseguita fino a che non è richiesta una iterazione sui dati  Esecuzione differita: valuto al momento della iterazione  Se modifico i dati ed avvio una nuova iterazione, avrò nuovi valori, aggiornati rispetto all’esecuzione precedente.  Una stessa query può essere ripetuta più volte restituendo ad ogni esecuzione un risultato valutato puntualmente sui dati di partenza. Dr. Paolo Casoto, Ph.D. - 2012
  • 20. + 20 Esecuzione immediata  E’ possibile anche invocare l’esecuzione immediata di una query LINQ.  Si invoca alla query l’esecuzione di uno dei metodi che restituiscono un tipo Enumerable  E.g.: metodo ToArray<T>(), ToList<T>()  E’ necessario tuttavia eseguire la query fra parentesi, per effettuare un generico cast ad un oggetto Enumerable.  Non è necessario che tale cast (che è verso un tipo generico) sia necessariamente tipato. Dr. Paolo Casoto, Ph.D. - 2012
  • 21. + 21 LINQ e le collezioni  LINQ può essere applicato, come abbiamo visto, agli array.  Tuttavia anche oggetti come gli oggetti List<T> possono essere utilizzati all’interno di query LINQ.  LINQ può essere applicato a ciascun oggetto che estenda IEnumerable<T>  E fra questi ci sono gli oggetti di tipo List<T>, nella loro connotazione generica Dr. Paolo Casoto, Ph.D. - 2012
  • 22. + 22 Esempio  Se la collezione sul quale operiamo la query è caratterizzata da oggetti di tipo T, allora all’interno della query stessa potremmo utilizzare le proprietà di T come criteri di filtraggio, ordinamento e selezione. static void TrovaAuroVeloci(List<Auto> mieAuto) { var autoVeloci= from c in mieAuto where c.Velocità> 180 select c; foreach (var auto in autoVeloci){ Console.WriteLine("{0} va veloce!", auto.nome );}} Doppia variabile con tipizzazione implicita Dr. Paolo Casoto, Ph.D. - 2012
  • 23. + 23 Tipizzare collezioni non tipizzate  Grazie al metodo ofType<T>() è possibile tipizzare anche una collezione che non supporta l’utilizzo dei tipi generici.  In questo modo risulta possibile utilizzare LINQ anche su queste tipologie di dati, anche se non implementano l’interfaccia IEnumerable<T>  La tipizzazione può essere utilizzata anche per filtrare tutti gli oggetti contenuti nella collezione che non concordano con il tipo T indicato nell’invocazione del metodo ofType<T>()  E.g.: filtro via dalla collezione tutto quello che non è int con ofType<int>(); Dr. Paolo Casoto, Ph.D. - 2012
  • 24. + 24 Esempio static void FiltraTipi() { ArrayList mioArray= new ArrayList(); mioArray object[] { 10, 400, 8, false, new Auto(), "string data" }); var mieiInteri= mioArray.OfType<int>(); foreach (int i in mieiInteri) { Console.WriteLine(“Valore: {0}", i); } } Stampa: 10, 400 ed 8, ignorando gli altri valori Dr. Paolo Casoto, Ph.D. - 2012
  • 25. + 25 Operatori LINQ  from … in: determina il contenitore dal quale dovranno essere estratti i dati nel corso della query;  where: definisce i criteri di filtraggio dei contenuti dal contenitore;  select: definisce cosa estrarre, a seguito dell’attività di filtraggio, dal contenitore;  join … on … equals … into: consente di eseguire il join fra i campi degli oggetti considerati;  Non ha nulla a che fare con il JOIN di SQL Dr. Paolo Casoto, Ph.D. - 2012
  • 26. + 26 Operatori LINQ  orderby … ascending / descending: definisce il criterio di ordinamento dei risultati;  group … by: definisce come i dati debbano essere raggruppati prima di essere restituiti.  In aggiunta ai costrutti descritti ve ne sono altri che possono essere applicati ai risultati della query  E.g.: Reverse<>(), ToArray<>(), ToList<>(),Distinct<>(), Union<>(), Inters ect<>(), Count<>(), Sum<>(), Min<>(), Max<>(), et al. Dr. Paolo Casoto, Ph.D. - 2012
  • 27. + 27 Le prime query LINQ  Il template più semplice per la formulazione di una query LINQ è sicuramente  var result = from oggetto in collezione select oggetto;  Per collezione, come più volte ricordato, possiamo intendere un DB relazionale, un array, una tabella in memoria, et al.  SELECT * FROM … Le query sono validate in fase di compilazione … gli errori di sintassi emergono subito !!!! Dr. Paolo Casoto, Ph.D. - 2012
  • 28. + 28 Il costrutto SELECT  Il costrutto select consente di definire quali oggetti della collezione (o loro proprietà) debbano essere inclusi nei risultati  Possiamo ad esempio includere solo il valore della proprietà X mediante la query  var result = from oggetto in collezione select oggetto.X;  Analogo della funzione di SELECT in SQL  Ma posso fare anche molto di più… Dr. Paolo Casoto, Ph.D. - 2012
  • 29. + 29 Il costrutto SELECT  …il costrutto SELECT mi consente di definire al volo nuovi tipi di dato anonimi  Si dice che la query LINQ “proietta” i propri risultati.  Non è possibile conoscere il tipo assunto dai dati fino al momento della compilazione  Per questo specifico motivo in questo caso è NECESSARIO utilizzare il costrutto var per ospitare il risultato della query  var result = from oggetto in collezione select new {oggetto.X, oggetto.Y}; Il tipo di dato di output è Dr. Paolo Casoto, Ph.D. - 2012 ANONIMO
  • 30. + 30 Il costrutto ORDERBY  Consente di definire il criterio di ordinamento dei dati  E’ possibile ordinare i dati secondo il criterio di ordinamento di ciascun tipo o di una delle sue proprietà.  var result = from oggetto in collezione orderby oggetto.nome select oggetto;  Per default l’ordinamento è di tipo crescente. Dr. Paolo Casoto, Ph.D. - 2012
  • 31. + 31 Operazioni insiemistiche  L’estensione dei metodi offerta dalla classe Enumerable consente di operare sui risultati delle query LINQ mediante operatori insiemistici:  Except: differenza insiemistica A/B  Intersect  Union  Concat: a differenza di Union mantiene gli eventuali elementi ripetuti.  Per ovviare alle duplicazioni è possibile utilizzare il metodo Distinct, analogo al corrispettivo SQL Dr. Paolo Casoto, Ph.D. - 2012
  • 32. + 32 Alcuni dettagli su LINQ  E’ possibile utilizzare funzioni aggregate sui dati restituiti dalle query, quali somma, media, minimo e massimo.  I costrutti delle query LINQ sono solo segnaposto per l’invocazione di metodi della classe Enumerable, i metodi Where, OrderBy, Select  Questo spiega la necessità del compilatore di verificare la corretta sintassi della query.  var result = collezione.OrderBy(oggetto => oggetto.nome).Select(oggetto => oggetto); Dr. Paolo Casoto, Ph.D. - 2012
  • 33. + 33 Eseguiamo insieme alcuni esempi LINQ  http://code.msdn.microsoft.com/101-LINQ-Samples- 3fb9811b/viewsamplepack  In particolare proviamo quelli più complessi, con l’utilizzo dei costrutti di raggruppamento e di join Dr. Paolo Casoto, Ph.D. - 2012
  • 34. + 34 LINQ to DataSet  Utilizziamo quanto imparato sulle potenzialità di LINQ per manipolare i dati presenti all’interno di un DataSet  Abbiamo già visto come ottenere un DataSet mediante il principio dell’accesso disconnesso ai dati di ADO.NET o mediante la creazione diretta via codice ed XML  Possiamo utilizzare LINQ su:  Tabelle, righe e colonne;  Mediante i TableDataReader  Mediante le classi di dati tipati  Generati automaticamente mediante importazione del DB da SQL Dr. Paolo Casoto, Ph.D. - 2012
  • 35. + 35 LINQ to DataSet  Abbiamo visto che le classi ADO.NET per la gestione dei DataSet ci offrono due modalità di accesso ai dati una tabella:  scorrimento di righe e colonne all’interno della tabella;  scorrimento lineare delle righe della tabella mediante un DataTableReader.  Grazie a LINQ possiamo percorrere definire modalità alternative di navigazione dei dati  Ma … gli oggetti utilizzati per rappresentare DataSet, tabelle, righe e colonne sono adatti ad essere utilizzati da LINQ ? Dr. Paolo Casoto, Ph.D. - 2012
  • 36. + 36 LINQ to DataSet  La risposta è no.  Come nel caso delle collezioni è necessario ovviare al problema mediante estensione dei metodi  Importiamo all’interno del progetto un riferimento all’assembly System.Data.DataSetExtensions.dll  Rende utilizzabili da LINQ non solo tabelle e righe, ma anche le tabelle fortemente tipate generate all’interno di un DataSet tipato  Estensioni delle classi TypedTableBase Dr. Paolo Casoto, Ph.D. - 2012
  • 37. + 37 LINQ to DataSet  Per trasformare una DataTable in un oggetto utilizzabile da LINQ, possiamo invocare il metodo AsEnumerable()  Restituisce un oggetto di tipo EnumerableRowCollection contenente un insieme di DataRows. Dr. Paolo Casoto, Ph.D. - 2012
  • 38. + 38 Esempio Trasformo la tabella static void MostraAutoBlu(DataTable data) in formato LINQ { var auto = from auto in data.AsEnumerable() where (string)auto["Colore"] == “Blu" select new{ ID = (int)auto[“Targa"], Produttore= (string)auto[“Produttore"] }; Console.WriteLine(“Auto Blu:"); foreach (var item in auto){ Console.WriteLine("-> Auto = {0} è{1}", item.ID, item.Produttore);} } Il tipo di dato di output è ANONIMO Dr. Paolo Casoto, Ph.D. - 2012
  • 39. + 39 Tipizzazione della query SQL  La query SQL potrebbe generare a runtime una eccezione nel caso in cui i campi abbiano un tipo diverso da quello che utilizziamo per il casting  Possiamo tipizzare la query forzando il tipo dei campi utilizzati  Controllo a tempo di compilazione  Per farlo possiamo utilizzare il metodo generico Field<T>() dell’oggetto DataRow Dr. Paolo Casoto, Ph.D. - 2012
  • 40. + 40 Esempio tipizzato static void MostraAutoBlu(DataTable data) { var auto = from auto in data.AsEnumerable() where auto.Field<String>("Colore“) == “Blu" select new{ ID = auto.Field<int>(“Targa“), Produttore= auto.Field<String>(“Produttore“) }; Console.WriteLine(“Auto Blu:"); foreach (var item in auto){ Console.WriteLine("-> Auto = {0} è{1}", item.ID, item.Produttore);} Dr. Paolo Casoto, Ph.D. - 2012
  • 41. + 41 Eseguiamo insieme alcuni esempi LINQ to DataSet  http://msdn.microsoft.com/en-us/library/bb399401.aspx  In particolare proviamo quelli più complessi, con l’utilizzo dei costrutti di raggruppamento e di join Dr. Paolo Casoto, Ph.D. - 2012
  • 42. + 42 Creare una DataTable da una query LINQ  E’ possibile riversare l’output di una query LINQ all’interno di una DataTable  Non può utilizzare alcuna proiezione all’interno della clausola SELECT.  Utilizziamo il metodo CopyToDataTable<T>()  E’ possibile anche ottenere da una query una vista, mediante il metodo AsDataView<T>() Dr. Paolo Casoto, Ph.D. - 2012
  • 43. + 43 Esempio  myDataGrid.DataSource = (from car in data.AsEnumerable()  where  car.Field<int>("CarID") > 5  select car).CopyToDataTable(); Dr. Paolo Casoto, Ph.D. - 2012