Procedura dettagliata: scrittura di query in C# (LINQ)
In questa procedura guidata vengono illustrate le funzionalità del linguaggio C# utilizzate per scrivere espressioni di query LINQ.Dopo avere completato questa procedura dettagliata sarà possibile passare agli esempi e alla documentazione per il provider LINQ specifico desiderato, ad esempio LINQ to SQL, LINQ to DataSets o LINQ to XML.
Prerequisiti
In questa procedura dettagliata richiede le funzionalità introdotte in Visual Studio 2008.
Per una versione video di questo argomento, vedere Procedura relativa a contenuti video: scrittura di query in C# (LINQ) (informazioni in lingua inglese).
Creazione di un progetto C#
Per creare un progetto
Avviare Visual Studio.
Nella barra del menu, scegliere File, Nuovo, Progetto.
Verrà visualizzata la finestra di dialogo Nuovo progetto.
Espandere Installato, espandere Modelli, espandere **Visual C#**e quindi scegliere Applicazione console.
Nella casella di testo Nome, un altro nome o accettare il nome predefinito e quindi scegliere il pulsante OK.
Il nuovo progetto verrà visualizzato in Esplora soluzioni.
Il progetto include un riferimento a System.Core.dll e una direttiva using per lo spazio dei nomi System.Linq.
Creazione di un'origine dati in memoria
L'origine dati per le query è un semplice elenco di oggetti Student.Ogni record Student contiene un nome, un cognome e una matrice di valori interi che rappresentano i punteggi dei test della classe.Copiare questo codice nel progetto.Tenere presente le seguenti caratteristiche:
La classe Student è costituita da proprietà implementate automaticamente.
Ogni studente nell'elenco viene inizializzato con un inizializzatore di oggetto.
L'elenco stesso viene inizializzato con un inizializzatore di raccolta.
Tutta la struttura dei dati verrà inizializzata e ne verrà creata un'istanza senza chiamate esplicite a un costruttore o accesso esplicito a un membro.Per ulteriori informazioni su queste nuove funzionalità, vedere Proprietà implementate automaticamente (Guida per programmatori C#) e Inizializzatori di oggetto e di raccolte (Guida per programmatori C#).
Per aggiungere l'origine dati
Aggiungere la classe Student e l'elenco di studenti inizializzato alla classe Program nel progetto.
public class Student { public string First { get; set; } public string Last { get; set; } public int ID { get; set; } public List<int> Scores; } // Create a data source by using a collection initializer. static List<Student> students = new List<Student> { new Student {First="Svetlana", Last="Omelchenko", ID=111, Scores= new List<int> {97, 92, 81, 60}}, new Student {First="Claire", Last="O’Donnell", ID=112, Scores= new List<int> {75, 84, 91, 39}}, new Student {First="Sven", Last="Mortensen", ID=113, Scores= new List<int> {88, 94, 65, 91}}, new Student {First="Cesar", Last="Garcia", ID=114, Scores= new List<int> {97, 89, 85, 82}}, new Student {First="Debra", Last="Garcia", ID=115, Scores= new List<int> {35, 72, 91, 70}}, new Student {First="Fadi", Last="Fakhouri", ID=116, Scores= new List<int> {99, 86, 90, 94}}, new Student {First="Hanying", Last="Feng", ID=117, Scores= new List<int> {93, 92, 80, 87}}, new Student {First="Hugo", Last="Garcia", ID=118, Scores= new List<int> {92, 90, 83, 78}}, new Student {First="Lance", Last="Tucker", ID=119, Scores= new List<int> {68, 79, 88, 92}}, new Student {First="Terry", Last="Adams", ID=120, Scores= new List<int> {99, 82, 81, 79}}, new Student {First="Eugene", Last="Zabokritski", ID=121, Scores= new List<int> {96, 85, 91, 60}}, new Student {First="Michael", Last="Tucker", ID=122, Scores= new List<int> {94, 92, 91, 91} } };
Per aggiungere un nuovo oggetto Student all'elenco Students
- Aggiungere un nuovo oggetto Student all'elenco Students e utilizzare un nome e i punteggi dei test desiderati.Provare a immettere tutte le informazioni sul nuovo studente in modo da acquisire dimestichezza con la sintassi per l'inizializzatore di oggetto.
Creazione della query
Per creare una query semplice
Nel metodo Main dell'applicazione creare una query semplice che, quando verrà eseguita, produrrà un elenco di tutti gli studenti il cui punteggio nel primo test era superiore a 90.Si noti che, poiché viene selezionato l'intero oggetto Student, il tipo della query è IEnumerable<Student>.Sebbene nel codice poteva essere utilizzata la tipizzazione implicita mediante la parola chiave var, è stata utilizzata la tipizzazione esplicita per illustrare dettagliatamente i risultati.Per ulteriori informazioni su var, vedere Variabili locali tipizzate in modo implicito (Guida per programmatori C#).
Tenere inoltre presente che la variabile di intervallo della query, student, funge da riferimento a ogni oggetto Student presente nell'origine, fornendo l'accesso al membro per ogni oggetto.
// Create the query.
// The first line could also be written as "var studentQuery ="
IEnumerable<Student> studentQuery =
from student in students
where student.Scores[0] > 90
select student;
Esecuzione della query
Per eseguire la query
Scrivere ora il ciclo foreach che consente di eseguire la query.In relazione al codice tenere presente quanto segue:
È possibile accedere a ogni elemento della sequenza restituita mediante la variabile di iterazione nel ciclo foreach.
Il tipo di questa variabile è Student e il tipo della variabile di query è compatibile, IEnumerable<Student>.
Dopo avere aggiunto questo codice, compilare ed eseguire l'applicazione premendo CTRL + F5 per visualizzare i risultati nella finestra della console.
// Execute the query.
// var could be used here also.
foreach (Student student in studentQuery)
{
Console.WriteLine("{0}, {1}", student.Last, student.First);
}
Per aggiungere un'altra condizione di filtro
È possibile combinare più condizioni booleane nella clausola where in modo da perfezionare ulteriormente la query.Il codice seguente aggiunge una condizione in modo che la query restituisca gli studenti di cui il primo punteggio era superiore a 90 e l'ultimo inferiore a 80.La clausola where dovrebbe essere analoga al codice seguente.
where student.Scores[0] > 90 && student.Scores[3] < 80
Per ulteriori informazioni, vedere Clausola where (Riferimento C#).
Modifica della query
Per ordinare i risultati
Sarà più semplice analizzare i risultati se vengono ordinati.È possibile ordinare la sequenza restituita in base a qualsiasi campo accessibile negli elementi di origine.Ad esempio, la clausola orderby riportata di seguito ordina i risultati alfabeticamente dalla A alla Z in base al cognome di ogni studente.Aggiungere alla query la clausola orderby riportata di seguito, subito dopo l'istruzione where e prima dell'istruzione select:
orderby student.Last ascending
Modificare ora la clausola orderby in modo da disporre i risultati in ordine inverso in base al punteggio del primo test, iniziando dal punteggio più alto fino a quello più basso.
orderby student.Scores[0] descending
Modificare la stringa di formato WriteLine in modo da poter visualizzare i punteggi:
Console.WriteLine("{0}, {1} {2}", student.Last, student.First, student.Scores[0]);
Per ulteriori informazioni, vedere Clausola orderby (Riferimento C#).
Per raggruppare i risultati
Il raggruppamento è una funzionalità potente nelle espressioni di query.Una query con una clausola group genera una sequenza di gruppi e ogni gruppo contiene un oggetto Key e una sequenza costituita da tutti i membri di tale gruppo.Nella nuova query riportata di seguito gli studenti vengono raggruppati utilizzando la prima lettera del cognome come chiave.
// studentQuery2 is an IEnumerable<IGrouping<char, Student>> var studentQuery2 = from student in students group student by student.Last[0];
Il tipo della query è stato ora modificato.Vengono ora generate una sequenza di gruppi con il tipo char come chiave e una sequenza di oggetti Student.Poiché il tipo della query è stato modificato, nel codice seguente viene modificato anche il ciclo di esecuzione foreach:
// studentGroup is a IGrouping<char, Student> foreach (var studentGroup in studentQuery2) { Console.WriteLine(studentGroup.Key); foreach (Student student in studentGroup) { Console.WriteLine(" {0}, {1}", student.Last, student.First); } }
Premere CTRL + F5 per eseguire l'applicazione e visualizzare i risultati nella finestra della console.
Per ulteriori informazioni, vedere Clausola group (Riferimento C#).
Per creare le variabili tipizzate in modo implicito
Codificare in modo esplicito IEnumerables di IGroupings può risultare noioso.È possibile scrivere la stessa query e il ciclo foreach in modo notevolmente più pratico utilizzando var.La parola chiave var non modifica i tipi degli oggetti ma indica solo al compilatore di dedurre i tipi.Modificare il tipo di studentQuery e la variabile di iterazione groupa var e rieseguire la query.Nel ciclo foreach interno la variabile di iterazione è ancora tipizzata come Student e la query funziona esattamente come prima.Impostare la variabile di iterazione s su var e rieseguire la query.Si otterranno esattamente gli stessi risultati.
var studentQuery3 = from student in students group student by student.Last[0]; foreach (var groupOfStudents in studentQuery3) { Console.WriteLine(groupOfStudents.Key); foreach (var student in groupOfStudents) { Console.WriteLine(" {0}, {1}", student.Last, student.First); } }
Per ulteriori informazioni su var, vedere Variabili locali tipizzate in modo implicito (Guida per programmatori C#).
Per ordinare i gruppi in base al valore della chiave
Quando si esegue la query precedente, i gruppi non sono in ordine alfabetico.Per modificare questo comportamento, è necessario fornire la clausola orderby dopo la clausola group.Per utilizzare la clausola orderby, è necessario però utilizzare prima un identificatore che funga da riferimento ai gruppi creati dalla clausola group.Fornire l'identificatore utilizzando la parola chiave into, come segue:
var studentQuery4 = from student in students group student by student.Last[0] into studentGroup orderby studentGroup.Key select studentGroup; foreach (var groupOfStudents in studentQuery4) { Console.WriteLine(groupOfStudents.Key); foreach (var student in groupOfStudents) { Console.WriteLine(" {0}, {1}", student.Last, student.First); } }
Quando si esegue questa query, i gruppi verranno ora ordinati alfabeticamente.
Per introdurre un identificatore utilizzando let
È possibile utilizzare la parola chiave let per introdurre un identificatore per qualsiasi risultato dell'espressione di query.Questo identificatore può risultare utile come nell'esempio seguente o può migliorare le prestazioni archiviando i risultati di un'espressione in modo da non doverla calcolare più volte.
// studentQuery5 is an IEnumerable<string> // This query returns those students whose // first test score was higher than their // average score. var studentQuery5 = from student in students let totalScore = student.Scores[0] + student.Scores[1] + student.Scores[2] + student.Scores[3] where totalScore / 4 < student.Scores[0] select student.Last + " " + student.First; foreach (string s in studentQuery5) { Console.WriteLine(s); }
Per ulteriori informazioni, vedere Clausola let (Riferimento C#).
Per utilizzare la sintassi del metodo in un'espressione di query
Come descritto in Sintassi di query e sintassi di metodi in LINQ (C#), alcune operazioni di query possono essere espresse solo utilizzando la sintassi del metodo.Nel codice seguente viene calcolato il punteggio totale per ogni Student nella sequenza di origine e viene quindi chiamato il metodo Average() sui risultati della query per calcolare il punteggio medio della classe.Notare l'utilizzo delle parentesi nell'espressione di query.
var studentQuery6 = from student in students let totalScore = student.Scores[0] + student.Scores[1] + student.Scores[2] + student.Scores[3] select totalScore; double averageScore = studentQuery6.Average(); Console.WriteLine("Class average score = {0}", averageScore);
Per trasformare o proiettare nella clausola select
Una query genera normalmente una sequenza i cui elementi differiscono dagli elementi delle sequenze di origine.Eliminare o impostare come commento la query precedente e il ciclo di esecuzione e sostituirli con il codice seguente.La query restituisce una sequenza di stringhe (non Students) che si riflette nel ciclo foreach.
IEnumerable<string> studentQuery7 = from student in students where student.Last == "Garcia" select student.First; Console.WriteLine("The Garcias in the class are:"); foreach (string s in studentQuery7) { Console.WriteLine(s); }
Il codice precedente in questa procedura dettagliata indica che il punteggio medio della classe è pari a circa 334.Per produrre una sequenza di Students il cui punteggio totale sia superiore alla media della classe, insieme al relativo Student ID, è possibile utilizzare un tipo anonimo nell'istruzione select:
var studentQuery8 = from student in students let x = student.Scores[0] + student.Scores[1] + student.Scores[2] + student.Scores[3] where x > averageScore select new { id = student.ID, score = x }; foreach (var item in studentQuery8) { Console.WriteLine("Student ID: {0}, Score: {1}", item.id, item.score); }
Passaggi successivi
Dopo aver acquisito dimestichezza con le caratteristiche principali delle query in C#, è possibile leggere la documentazione e gli esempi per il tipo specifico di provider LINQ desiderato:
Vedere anche
Attività
Procedura dettagliata: scrittura delle query in Visual Basic
Concetti
Espressioni di query LINQ (Guida per programmatori C#)