Transformations de données avec LINQ (C#)

LINQ (Language Integrated Query) ne gère pas uniquement la récupération des données.C'est également un outil puissant pour la transformation de données.En utilisant une requête LINQ, vous pouvez utiliser une séquence source en entrée et la modifier de nombreuses façons pour créer une séquence de sortie.Vous pouvez modifier la séquence elle-même sans modifier les éléments eux-mêmes triant et en le regroupement. Mais éventuellement la plupart de fonctionnalité puissante des requêtes d' LINQ est la possibilité de créer de nouveaux types.Cette opération est effectuée dans la clause select.Par exemple, il est possible de réaliser les tâches suivantes :

  • Fusionner plusieurs séquences d'entrée dans une séquence de sortie unique avec un type nouveau.

  • Créer des séquences de sortie dont les éléments se composent d'une seule propriété ou de plusieurs propriétés de chaque élément de la séquence source.

  • Créer des séquences de sortie dont les éléments se composent des résultats des opérations effectuées sur les données sources.

  • Créer des séquences de sortie dans un format différent.Par exemple, vous pouvez transformer des données de lignes ou de fichiers texte SQL en XML.

Cette liste d'exemples n'est pas exhaustive.Bien sûr, ces transformations peuvent être combinées de plusieurs façons dans la même requête.Par ailleurs, la séquence de sortie d'une requête peut être utilisée comme séquence d'entrée pour une nouvelle requête.

Combinaison de plusieurs entrées en une séquence de sortie

Vous pouvez utiliser une requête LINQ pour créer une séquence de sortie qui contient des éléments de plusieurs séquences d'entrée.L'exemple suivant montre comment combiner deux structures de données en mémoire, mais ces principes peuvent être appliqués pour combiner des données de sources XML, SQL ou DataSet.Prenons l'exemple des deux types de classe suivants :

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; }
}

L'exemple suivant présente la requête :

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
 */

Pour plus d'informations, consultez join, clause (Référence C#) et select, clause (Référence C#).

Sélection d'un sous-ensemble de chaque élément source

Il existe deux méthodes principales pour sélectionner un sous-ensemble de chaque élément de la séquence source :

  1. Pour sélectionner un seul membre de l'élément source, utilisez l'opérateur point.Dans l'exemple suivant, supposons qu'un objet Customer contient plusieurs propriétés publiques y compris une chaîne nommée City.Une fois exécutée, cette requête génère une séquence de sortie de chaînes.

    var query = from cust in Customers
                select cust.City;
    
  2. Pour créer des éléments qui contiennent plusieurs propriétés de l'élément source, vous pouvez utiliser un initialiseur d'objet avec un objet nommé ou un type anonyme.L'exemple suivant montre comment utiliser un type anonyme pour encapsuler deux propriétés de chaque élément Customer :

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

Pour plus d'informations, consultez Initialiseurs d'objets et de collection (Guide de programmation C#) et Types anonymes (Guide de programmation C#).

Transformation d'objets en mémoire en XML

Les requêtes LINQ permettent de transformer facilement des données entre des structures de données en mémoire, des bases de données SQL, des groupes de données ADO.NET et des flux de données ou des documents XML.L'exemple suivant transforme des objets d'une structure de données en mémoire en éléments XML.

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 x = String.Format("{0},{1},{2},{3}", student.Scores[0],
                    student.Scores[1], student.Scores[2], student.Scores[3])
            select new XElement("student",
                       new XElement("First", student.First),
                       new XElement("Last", student.Last),
                       new XElement("Scores", x)
                    ) // 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();
    }
}

Le code génère la sortie XML suivante :

< 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>

Pour plus d'informations, consultez Creating XML Trees in C#.

Opérations sur les éléments sources

Une séquence de sortie ne contient pas toujours des éléments ou des propriétés d'élément de la séquence source.La sortie peut être une séquence de valeurs calculée avec les éléments sources comme arguments d'entrée.La requête simple suivante, lorsqu'elle est exécutée, génère en sortie une séquence de chaînes dont les valeurs représentent un calcul basé sur la séquence source d'éléments de type double.

[!REMARQUE]

Les méthodes d'appel dans les expressions de requête ne sont pas prises en charge si la requête est traduite dans un autre domaine.Par exemple, vous ne pouvez pas appeler de méthode C# ordinaire dans LINQ to SQL car SQL Server n'a pas de contexte pour cette méthode.Toutefois, vous pouvez mapper des procédures stockées à des méthodes et appeler celles-ci.Pour plus d'informations, consultez Stored Procedures: Mapping and Calling (LINQ to SQL).

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

        // Query.
        IEnumerable<string> query =
            from rad in radii
            select String.Format("Area = {0}", (rad * rad) * 3.14);

        // 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.56
    Area = 28.26
*/

Voir aussi

Tâches

Comment : combiner des données avec LINQ à l'aide de jointures (Visual Basic)

Référence

select, clause (Référence C#)

Concepts

Expressions de requête LINQ (Guide de programmation C#)

Autres ressources

LINQ (Language-Integrated Query)

LINQ to SQL

LINQ to DataSet

LINQ to XML