Trasformazioni dati con LINQ (C#)Data Transformations with LINQ (C#)

LINQ (Language-Integrated Query)Language-Integrated Query (LINQ) non riguarda solo il recupero dei dati.is not only about retrieving data. È anche un potente strumento per la trasformazione dei dati.It is also a powerful tool for transforming data. Con una query LINQLINQ è possibile usare una sequenza di origine come input e modificarla in molti modi per creare una nuova sequenza di output.By using a LINQLINQ query, you can use a source sequence as input and modify it in many ways to create a new output sequence. È possibile modificare la sequenza senza modificare gli elementi con operazioni di ordinamento e raggruppamento.You can modify the sequence itself without modifying the elements themselves by sorting and grouping. Ma probabilmente la funzionalità più potente delle query LINQLINQ è la possibilità di creare nuovi tipi.But perhaps the most powerful feature of LINQLINQ queries is the ability to create new types. Questa operazione viene eseguita nella clausola select.This is accomplished in the select clause. Ad esempio, è possibile effettuare le attività seguenti:For example, you can perform the following tasks:

  • Unire più sequenze di input in un'unica sequenza di output con un nuovo tipo.Merge multiple input sequences into a single output sequence that has a new type.

  • Creare sequenze di output i cui elementi sono costituiti da una o più proprietà di ogni elemento nella sequenza di origine.Create output sequences whose elements consist of only one or several properties of each element in the source sequence.

  • Creare sequenze di output i cui elementi sono costituiti dai risultati delle operazioni eseguite sui dati di origine.Create output sequences whose elements consist of the results of operations performed on the source data.

  • Creare sequenze di output in un formato diverso.Create output sequences in a different format. Ad esempio, è possibile trasformare i dati da righe SQL o file di testo in XML.For example, you can transform data from SQL rows or text files into XML.

Questi sono solo alcuni esempi.These are just several examples. Naturalmente, queste trasformazioni possono essere combinate in modi diversi nella stessa query.Of course, these transformations can be combined in various ways in the same query. Inoltre, la sequenza di output di una query può essere usata come sequenza di input per una nuova query.Furthermore, the output sequence of one query can be used as the input sequence for a new query.

Unione di più input in un'unica sequenza di outputJoining Multiple Inputs into One Output Sequence

È possibile usare una query LINQLINQ per creare una sequenza di output che contiene gli elementi di più di una sequenza di input.You can use a LINQLINQ query to create an output sequence that contains elements from more than one input sequence. Nell'esempio seguente viene illustrato come combinare due strutture di dati in memoria, ma è possibile applicare gli stessi principi per combinare dati da origini XML, SQL o DataSet.The following example shows how to combine two in-memory data structures, but the same principles can be applied to combine data from XML or SQL or DataSet sources. Si supponga di avere questi tipi di classi:Assume the following two class types:

class Student
{
    public string First { get; set; }
    public string Last {get; set;}
    public int ID { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public List<int> Scores;
}

class Teacher
{
    public string First { get; set; }
    public string Last { get; set; }
    public int ID { get; set; } 
    public string City { get; set; }
}

Nell'esempio riportato di seguito è visualizzata la query:The following example shows the query:

class DataTransformations
{
    static void Main()
    {
        // Create the first data source.
        List<Student> students = new List<Student>()
        {
            new Student { First="Svetlana",
                Last="Omelchenko",
                ID=111,
                Street="123 Main Street",
                City="Seattle",
                Scores= new List<int> { 97, 92, 81, 60 } },
            new Student { First="Claire",
                Last="O’Donnell",
                ID=112,
                Street="124 Main Street",
                City="Redmond",
                Scores= new List<int> { 75, 84, 91, 39 } },
            new Student { First="Sven",
                Last="Mortensen",
                ID=113,
                Street="125 Main Street",
                City="Lake City",
                Scores= new List<int> { 88, 94, 65, 91 } },
        };

        // Create the second data source.
        List<Teacher> teachers = new List<Teacher>()
        {                
            new Teacher { First="Ann", Last="Beebe", ID=945, City="Seattle" },
            new Teacher { First="Alex", Last="Robinson", ID=956, City="Redmond" },
            new Teacher { First="Michiyo", Last="Sato", ID=972, City="Tacoma" }
        };
        
        // Create the query.
        var peopleInSeattle = (from student in students
                    where student.City == "Seattle"
                    select student.Last)
                    .Concat(from teacher in teachers
                            where teacher.City == "Seattle"
                            select teacher.Last);

        Console.WriteLine("The following students and teachers live in Seattle:");
        // Execute the query.
        foreach (var person in peopleInSeattle)
        {
            Console.WriteLine(person);
        }
        
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    The following students and teachers live in Seattle:
    Omelchenko
    Beebe
 */

Per altre informazioni, vedere Clausola join e Clausola select.For more information, see join clause and select clause.

Selezione di un sottoinsieme di ogni elemento di origineSelecting a Subset of each Source Element

Esistono due modi principali per selezionare un sottoinsieme di ogni elemento nella sequenza di origine:There are two primary ways to select a subset of each element in the source sequence:

  1. Per selezionare solo un membro dell'elemento di origine, usare l'operazione con punto.To select just one member of the source element, use the dot operation. Nell'esempio seguente si supponga che un oggetto Customer contenga diverse proprietà pubbliche tra cui una stringa denominata City.In the following example, assume that a Customer object contains several public properties including a string named City. Quando viene eseguita, questa query produce una sequenza di output di stringhe.When executed, this query will produce an output sequence of strings.

    var query = from cust in Customers  
                select cust.City;  
    
  2. Per creare gli elementi che contengono più di una proprietà dall'elemento di origine, è possibile usare un inizializzatore di oggetto con un oggetto denominato o un tipo anonimo.To create elements that contain more than one property from the source element, you can use an object initializer with either a named object or an anonymous type. Nell'esempio seguente viene illustrato l'uso di un tipo anonimo per incapsulare due proprietà da ogni elemento Customer:The following example shows the use of an anonymous type to encapsulate two properties from each Customer element:

    var query = from cust in Customer  
                select new {Name = cust.Name, City = cust.City};  
    

Per altre informazioni, vedere Inizializzatori di oggetto e di insieme e Tipi anonimi.For more information, see Object and Collection Initializers and Anonymous Types.

Trasformazione di oggetti in memoria in XMLTransforming in-Memory Objects into XML

Le query LINQLINQ semplificano la trasformazione dei dati tra strutture di dati in memoria, database SQL, set di dati ADO.NET e flussi o documenti XML.LINQLINQ queries make it easy to transform data between in-memory data structures, SQL databases, ADO.NET Datasets and XML streams or documents. Nell'esempio seguente gli oggetti di una struttura di dati in memoria vengono trasformati in elementi XML.The following example transforms objects in an in-memory data structure into XML elements.

class XMLTransform
{
    static void Main()
    {            
        // Create the data source by using a collection initializer.
        // The Student class was defined previously in this topic.
        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}},
        };

        // Create the query.
        var studentsToXML = new XElement("Root",
            from student in students
            let scores = string.Join(",", student.Scores)
            select new XElement("student",
                       new XElement("First", student.First),
                       new XElement("Last", student.Last),
                       new XElement("Scores", scores)
                    ) // end "student"
                ); // end "Root"

        // Execute the query.
        Console.WriteLine(studentsToXML);

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}

Il codice genera il seguente output XML:The code produces the following XML output:

<Root>  
  <student>  
    <First>Svetlana</First>  
    <Last>Omelchenko</Last>  
    <Scores>97,92,81,60</Scores>  
  </student>  
  <student>  
    <First>Claire</First>  
    <Last>O'Donnell</Last>  
    <Scores>75,84,91,39</Scores>  
  </student>  
  <student>  
    <First>Sven</First>  
    <Last>Mortensen</Last>  
    <Scores>88,94,65,91</Scores>  
  </student>  
</Root>  

Per altre informazioni, vedere Creazione di alberi XML in C# (LINQ to XML).For more information, see Creating XML Trees in C# (LINQ to XML).

Esecuzione di operazioni su elementi di originePerforming Operations on Source Elements

Una sequenza di output potrebbe non contenere elementi o proprietà degli elementi della sequenza di origine.An output sequence might not contain any elements or element properties from the source sequence. L'output potrebbe invece essere una sequenza di valori che viene calcolata usando gli elementi di origine come argomenti di input.The output might instead be a sequence of values that is computed by using the source elements as input arguments. La seguente query semplice, quando viene eseguita, restituisce una sequenza di stringhe i cui valori rappresentano un calcolo basato sulla sequenza di origine di elementi di tipo double.The following simple query, when it is executed, outputs a sequence of strings whose values represent a calculation based on the source sequence of elements of type double.

Nota

La chiamata ai metodi nelle espressioni di query non è supportata se la query verrà traslata in un altro dominio.Calling methods in query expressions is not supported if the query will be translated into some other domain. Ad esempio, non è possibile chiamare un normale metodo C# in LINQ to SQLLINQ to SQL perché SQL Server non offre alcun contesto.For example, you cannot call an ordinary C# method in LINQ to SQLLINQ to SQL because SQL Server has no context for it. Tuttavia, è possibile eseguire il mapping delle stored procedure ai metodi e chiamarli.However, you can map stored procedures to methods and call those. Per altre informazioni, vedere Stored procedure.For more information, see Stored Procedures.

class FormatQuery
{
    static void Main()
    {            
        // Data source.
        double[] radii = { 1, 2, 3 };

        // Query.
        IEnumerable<string> query =
            from rad in radii
            select $"Area = {rad * rad * Math.PI:F2}";

        // Query execution. 
        foreach (string s in query)
            Console.WriteLine(s);

        // Keep the console open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    Area = 3.14
    Area = 12.57
    Area = 28.27
*/

Vedere ancheSee also