Przekształcanie danych za pomocą LINQ (C#)Data Transformations with LINQ (C#)

Zapytanie zintegrowane z językiem (LINQ) nie tylko pobiera dane.Language-Integrated Query (LINQ) is not only about retrieving data. Jest to również zaawansowane narzędzie do przekształcania danych.It is also a powerful tool for transforming data. Używając zapytania LINQ, można użyć sekwencji źródłowej jako danych wejściowych i zmodyfikować ją na wiele sposobów, aby utworzyć nową sekwencję wyjściową.By using a LINQ query, you can use a source sequence as input and modify it in many ways to create a new output sequence. Można zmodyfikować samą sekwencję bez modyfikowania samych elementów przez sortowanie i grupowanie.You can modify the sequence itself without modifying the elements themselves by sorting and grouping. Jednak prawdopodobnie najbardziej wydajną funkcją zapytań LINQ jest możliwość tworzenia nowych typów.But perhaps the most powerful feature of LINQ queries is the ability to create new types. Jest to realizowane w klauzuli SELECT .This is accomplished in the select clause. Na przykład należy wykonać następujące zadania:For example, you can perform the following tasks:

  • Scalanie wielu sekwencji wejściowych w jedną sekwencję wyjściową, która ma nowy typ.Merge multiple input sequences into a single output sequence that has a new type.

  • Utwórz sekwencje danych wyjściowych, których elementy składają się tylko z jednej lub kilku właściwości każdego elementu w sekwencji źródłowej.Create output sequences whose elements consist of only one or several properties of each element in the source sequence.

  • Utwórz sekwencje danych wyjściowych, których elementy składają się z wyników operacji wykonanych na danych źródłowych.Create output sequences whose elements consist of the results of operations performed on the source data.

  • Utwórz sekwencje wyjściowe w innym formacie.Create output sequences in a different format. Na przykład możesz przekształcić dane z wierszy SQL lub plików tekstowych do formatu XML.For example, you can transform data from SQL rows or text files into XML.

Poniżej przedstawiono kilka przykładów.These are just several examples. Oczywiście te przekształcenia można łączyć na różne sposoby w tym samym zapytaniu.Of course, these transformations can be combined in various ways in the same query. Ponadto sekwencja wyjściowa jednego zapytania może służyć jako sekwencja wejściowa dla nowej kwerendy.Furthermore, the output sequence of one query can be used as the input sequence for a new query.

Łączenie wielu danych wejściowych w jedną sekwencję wyjściowąJoining Multiple Inputs into One Output Sequence

Za pomocą zapytania LINQ można utworzyć sekwencję wyjściową zawierającą elementy z więcej niż jednej sekwencji danych wejściowych.You can use a LINQ query to create an output sequence that contains elements from more than one input sequence. Poniższy przykład pokazuje, jak połączyć dwie struktury danych w pamięci, ale te same zasady można stosować do łączenia danych ze źródeł XML lub SQL lub zestawów danych.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. Założono następujące dwa typy klas: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; }
}

W poniższym przykładzie pokazano zapytanie: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
 */

Aby uzyskać więcej informacji, zobacz Klauzula join i klauzula SELECT.For more information, see join clause and select clause.

Wybranie podzestawu każdego elementu źródłowegoSelecting a Subset of each Source Element

Istnieją dwa podstawowe sposoby wybierania podzbioru każdego elementu w sekwencji źródłowej:There are two primary ways to select a subset of each element in the source sequence:

  1. Aby zaznaczyć tylko jeden element członkowski elementu źródłowego, użyj operacji z kropką.To select just one member of the source element, use the dot operation. W poniższym przykładzie Załóżmy, że obiekt Customer zawiera kilka właściwości publicznych, w tym ciąg o nazwie City.In the following example, assume that a Customer object contains several public properties including a string named City. Po wykonaniu to zapytanie będzie generować sekwencję wyjściową ciągów.When executed, this query will produce an output sequence of strings.

    var query = from cust in Customers  
                select cust.City;  
    
  2. Aby utworzyć elementy, które zawierają więcej niż jedną właściwość z elementu źródłowego, można użyć inicjatora obiektów z obiektem nazwanym lub typem anonimowym.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. W poniższym przykładzie pokazano użycie typu anonimowego do hermetyzacji dwóch właściwości z każdego elementu 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};  
    

Aby uzyskać więcej informacji, zobacz Inicjatory obiektów i kolekcji oraz Typy anonimowe.For more information, see Object and Collection Initializers and Anonymous Types.

Przekształcanie obiektów w pamięci do formatu XMLTransforming in-Memory Objects into XML

Zapytania LINQ ułatwiają Przekształcanie danych między strukturami danych w pamięci, bazami danych SQL, ADO.NETmi i strumieniami XML.LINQ queries make it easy to transform data between in-memory data structures, SQL databases, ADO.NET Datasets and XML streams or documents. Poniższy przykład przekształca obiekty w strukturze danych w pamięci na elementy 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();
    }
}

Kod generuje następujące dane wyjściowe 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>  

Aby uzyskać więcej informacji, zobacz Tworzenie drzew XML C# w (LINQ to XML).For more information, see Creating XML Trees in C# (LINQ to XML).

Wykonywanie operacji na elementach źródłowychPerforming Operations on Source Elements

Sekwencja wyjściowa może nie zawierać żadnych elementów ani właściwości elementów z sekwencji źródłowej.An output sequence might not contain any elements or element properties from the source sequence. Wyjście może zamiast tego być sekwencją wartości, które są obliczane przy użyciu elementów źródłowych jako argumentów wejściowych.The output might instead be a sequence of values that is computed by using the source elements as input arguments. Następujące proste zapytanie, gdy jest wykonywane, wyprowadza sekwencję ciągów, których wartości reprezentują obliczenia na podstawie sekwencji źródłowej elementów typu 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.

Uwaga

Metody wywołujące w wyrażeniach zapytań nie są obsługiwane, jeśli zapytanie zostanie przetłumaczone na inną domenę.Calling methods in query expressions is not supported if the query will be translated into some other domain. Na przykład nie można wywołać metody zwykłej C# w LINQ do SQLLINQ to SQL, ponieważ SQL Server nie ma kontekstu dla tego elementu.For example, you cannot call an ordinary C# method in LINQ do SQLLINQ to SQL because SQL Server has no context for it. Można jednak mapować procedury składowane na metody i wywoływać je.However, you can map stored procedures to methods and call those. Aby uzyskać więcej informacji, zobacz procedury składowane.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
*/

Zobacz takżeSee also