Wprowadzenie do kwerend LINQ (C#)Introduction to LINQ Queries (C#)

Zapytanie jest wyrażeniem, które pobiera dane ze źródła danych.A query is an expression that retrieves data from a data source. Zapytania są zwykle wyrażane w wyspecjalizowanym języku zapytań.Queries are usually expressed in a specialized query language. Różne języki zostały opracowane z upływem czasu dla różnych typów źródeł danych, na przykład SQL dla relacyjnych baz danych i XQuery dla XML.Different languages have been developed over time for the various types of data sources, for example SQL for relational databases and XQuery for XML. W związku z tym deweloperzy musieli poznać nowy język zapytań dla każdego typu źródła danych lub formatu danych, które muszą być obsługiwane przez program.Therefore, developers have had to learn a new query language for each type of data source or data format that they must support. LINQLINQ upraszcza tę sytuację, oferując spójny model do pracy z danymi w różnych rodzajach źródeł danych i formatach.simplifies this situation by offering a consistent model for working with data across various kinds of data sources and formats. W zapytaniu LINQLINQ zawsze pracujesz z obiektami.In a LINQLINQ query, you are always working with objects. Te same podstawowe wzorce kodowania służą do wykonywania zapytań i przekształcania danych w dokumentach XML, baz danych SQL, ADO.NET, kolekcjach programu .NET i innych formatach, dla których jest dostępny dostawca LINQLINQ.You use the same basic coding patterns to query and transform data in XML documents, SQL databases, ADO.NET Datasets, .NET collections, and any other format for which a LINQLINQ provider is available.

Trzy części operacji zapytaniaThree Parts of a Query Operation

Wszystkie operacje zapytań LINQLINQ składają się z trzech odrębnych akcji:All LINQLINQ query operations consist of three distinct actions:

  1. Uzyskanie źródła danych.Obtain the data source.

  2. Utwórz zapytanie.Create the query.

  3. Wykonaj zapytanie.Execute the query.

Poniższy przykład pokazuje, jak trzy części operacji zapytania są wyrażone w kodzie źródłowym.The following example shows how the three parts of a query operation are expressed in source code. W przykładzie jest wykorzystywana tablica liczb całkowitych jako źródło danych dla wygody; Jednak te same koncepcje odnoszą się również do innych źródeł danych.The example uses an integer array as a data source for convenience; however, the same concepts apply to other data sources also. Ten przykład jest określany w pozostałej części tego tematu.This example is referred to throughout the rest of this topic.

class IntroToLINQ
{        
    static void Main()
    {
        // The Three Parts of a LINQ Query:
        // 1. Data source.
        int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

        // 2. Query creation.
        // numQuery is an IEnumerable<int>
        var numQuery =
            from num in numbers
            where (num % 2) == 0
            select num;

        // 3. Query execution.
        foreach (int num in numQuery)
        {
            Console.Write("{0,1} ", num);
        }
    }
}

Na poniższej ilustracji przedstawiono wykonywanie operacji zapytania.The following illustration shows the complete query operation. W LINQLINQ wykonywanie zapytania różni się od samego zapytania; Innymi słowy, nie pobrano żadnych danych tylko przez utworzenie zmiennej zapytania.In LINQLINQ the execution of the query is distinct from the query itself; in other words you have not retrieved any data just by creating a query variable.

Diagram pełnej operacji zapytania LINQ.

Źródło danychThe Data Source

W poprzednim przykładzie, ponieważ źródło danych jest tablicą, niejawnie obsługuje interfejs ogólny IEnumerable<T>.In the previous example, because the data source is an array, it implicitly supports the generic IEnumerable<T> interface. Oznacza to, że można je zbadać przy użyciu LINQLINQ.This fact means it can be queried with LINQLINQ. Zapytanie jest wykonywane w instrukcji foreach i foreach wymaga IEnumerable lub IEnumerable<T>.A query is executed in a foreach statement, and foreach requires IEnumerable or IEnumerable<T>. Typy obsługujące IEnumerable<T> lub interfejs pochodny, takie jak generyczne IQueryable<T>, są nazywane typami Queryable.Types that support IEnumerable<T> or a derived interface such as the generic IQueryable<T> are called queryable types.

Typ Queryable nie wymaga modyfikacji ani specjalnego traktowania, które ma być źródłem danych LINQLINQ.A queryable type requires no modification or special treatment to serve as a LINQLINQ data source. Jeśli dane źródłowe nie są jeszcze w pamięci jako typ queryable, dostawca LINQLINQ musi je przedstawić jako taki.If the source data is not already in memory as a queryable type, the LINQLINQ provider must represent it as such. Na przykład LINQ do XMLLINQ to XML ładuje dokument XML do typu XElement Queryable:For example, LINQ do XMLLINQ to XML loads an XML document into a queryable XElement type:

// Create a data source from an XML document.
// using System.Xml.Linq;
XElement contacts = XElement.Load(@"c:\myContactList.xml");

Przy LINQ do SQLLINQ to SQLnależy najpierw utworzyć mapowanie relacyjne obiektu w czasie projektowania ręcznie lub za pomocą narzędzi LINQ to SQL w programie Visual Studio w programie Visual Studio.With LINQ do SQLLINQ to SQL, you first create an object-relational mapping at design time either manually or by using the LINQ to SQL Tools in Visual Studio in Visual Studio. Zapytania są zapisywane względem obiektów, a w czasie wykonywania LINQ do SQLLINQ to SQL obsługuje komunikację z bazą danych.You write your queries against the objects, and at run-time LINQ do SQLLINQ to SQL handles the communication with the database. W poniższym przykładzie Customers reprezentuje określoną tabelę w bazie danych, a typ wyniku zapytania, IQueryable<T>, pochodzi z IEnumerable<T>.In the following example, Customers represents a specific table in the database, and the type of the query result, IQueryable<T>, derives from IEnumerable<T>.

Northwnd db = new Northwnd(@"c:\northwnd.mdf");  
  
// Query for customers in London.  
IQueryable<Customer> custQuery =  
    from cust in db.Customers  
    where cust.City == "London"  
    select cust;  

Aby uzyskać więcej informacji o sposobach tworzenia określonych typów źródeł danych, zapoznaj się z dokumentacją dla różnych dostawców LINQLINQ.For more information about how to create specific types of data sources, see the documentation for the various LINQLINQ providers. Podstawowa reguła jest jednak bardzo prosta: LINQLINQ źródłem danych jest każdy obiekt, który obsługuje ogólny interfejs IEnumerable<T> lub interfejs, który z niego dziedziczy.However, the basic rule is very simple: a LINQLINQ data source is any object that supports the generic IEnumerable<T> interface, or an interface that inherits from it.

Uwaga

Typy takie jak ArrayList obsługujące nieogólny interfejs IEnumerable mogą również służyć jako źródło danych LINQLINQ.Types such as ArrayList that support the non-generic IEnumerable interface can also be used as a LINQLINQ data source. Aby uzyskać więcej informacji, zobacz How to: Query a ArrayList with LINQC#().For more information, see How to: Query an ArrayList with LINQ (C#).

ZapytanieThe Query

Zapytanie określa, jakie informacje mają być pobierane ze źródła danych lub źródeł.The query specifies what information to retrieve from the data source or sources. Opcjonalnie zapytanie określa również, jak te informacje powinny być sortowane, grupowane i ukształtowane przed zwróceniem.Optionally, a query also specifies how that information should be sorted, grouped, and shaped before it is returned. Zapytanie jest przechowywane w zmiennej zapytania i inicjowane z wyrażeniem zapytania.A query is stored in a query variable and initialized with a query expression. Aby ułatwić Pisanie zapytań, C# wprowadzono nową składnię zapytania.To make it easier to write queries, C# has introduced new query syntax.

Zapytanie w poprzednim przykładzie zwraca wszystkie liczby parzyste z tablicy liczb całkowitych.The query in the previous example returns all the even numbers from the integer array. Wyrażenie zapytania zawiera trzy klauzule: from, where i select.The query expression contains three clauses: from, where and select. (Jeśli znasz program SQL, zobaczysz, że kolejność klauzul została odwrócona z kolejności w języku SQL). Klauzula from określa źródło danych, klauzula where stosuje filtr, a klauzula select określa typ zwracanych elementów.(If you are familiar with SQL, you will have noticed that the ordering of the clauses is reversed from the order in SQL.) The from clause specifies the data source, the where clause applies the filter, and the select clause specifies the type of the returned elements. Te i inne klauzule zapytań są szczegółowo omówione w sekcji wyrażenia zapytania LINQ .These and the other query clauses are discussed in detail in the LINQ Query Expressions section. Na razie ważnym punktem jest to, że w LINQLINQzmienna zapytania nie przyjmuje żadnej akcji i nie zwraca żadnych danych.For now, the important point is that in LINQLINQ, the query variable itself takes no action and returns no data. Po prostu przechowuje informacje, które są wymagane do wygenerowania wyników, gdy zapytanie jest wykonywane w późniejszym momencie.It just stores the information that is required to produce the results when the query is executed at some later point. Aby uzyskać więcej informacji o tym, jak zapytania są konstruowane w tle, zobacz standardowe operatory zapytańC#— omówienie ().For more information about how queries are constructed behind the scenes, see Standard Query Operators Overview (C#).

Uwaga

Zapytania można również wyrazić przy użyciu składni metody.Queries can also be expressed by using method syntax. Aby uzyskać więcej informacji, zobacz składnia zapytań i składnia metod w LINQ.For more information, see Query Syntax and Method Syntax in LINQ.

Wykonywanie zapytaniaQuery Execution

Wykonanie odroczoneDeferred Execution

Jak wspomniano wcześniej, zmienna zapytania zawiera tylko polecenia zapytania.As stated previously, the query variable itself only stores the query commands. Rzeczywiste wykonanie zapytania jest odroczone do czasu przetworzenia iteracji względem zmiennej zapytania w instrukcji foreach.The actual execution of the query is deferred until you iterate over the query variable in a foreach statement. Koncepcja ta jest nazywana wykonywaniem odroczonym i przedstawiono w poniższym przykładzie:This concept is referred to as deferred execution and is demonstrated in the following example:

//  Query execution. 
foreach (int num in numQuery)
{
    Console.Write("{0,1} ", num);
}

Instrukcja foreach jest również miejscem, w którym pobierane są wyniki zapytania.The foreach statement is also where the query results are retrieved. Na przykład w poprzedniej kwerendzie Zmienna iteracji num przechowuje każdą wartość (pojedynczo) w zwracanej sekwencji.For example, in the previous query, the iteration variable num holds each value (one at a time) in the returned sequence.

Ponieważ sama zmienna zapytania nigdy nie przechowuje wyników zapytania, można wykonać ją tak często, jak chcesz.Because the query variable itself never holds the query results, you can execute it as often as you like. Na przykład może istnieć baza danych, która jest stale aktualizowana przez oddzielną aplikację.For example, you may have a database that is being updated continually by a separate application. W aplikacji można utworzyć jedno zapytanie, które pobiera najnowsze dane, i można wykonać je wielokrotnie w pewnym interwale, aby pobierać różne wyniki za każdym razem.In your application, you could create one query that retrieves the latest data, and you could execute it repeatedly at some interval to retrieve different results every time.

Wymuszanie natychmiastowego wykonaniaForcing Immediate Execution

Zapytania, które wykonują funkcje agregacji dla zakresu elementów źródłowych, muszą najpierw wykonać iterację tych elementów.Queries that perform aggregation functions over a range of source elements must first iterate over those elements. Przykładami takich zapytań są Count, Max, Averagei First.Examples of such queries are Count, Max, Average, and First. Te wykonywanie bez jawnej instrukcji foreach, ponieważ zapytanie musi używać foreach, aby można było zwrócić wynik.These execute without an explicit foreach statement because the query itself must use foreach in order to return a result. Należy zauważyć, że te typy zapytań zwracają pojedynczą wartość, a nie kolekcję IEnumerable.Note also that these types of queries return a single value, not an IEnumerable collection. Następujące zapytanie zwraca liczbę liczb parzystych w tablicy źródłowej:The following query returns a count of the even numbers in the source array:

var evenNumQuery = 
    from num in numbers
    where (num % 2) == 0
    select num;

int evenNumCount = evenNumQuery.Count();

Aby wymusić natychmiastowe wykonywanie dowolnego zapytania i buforować jego wyniki, można wywołać metody ToList lub ToArray.To force immediate execution of any query and cache its results, you can call the ToList or ToArray methods.

List<int> numQuery2 =
    (from num in numbers
     where (num % 2) == 0
     select num).ToList();

// or like this:
// numQuery3 is still an int[]

var numQuery3 =
    (from num in numbers
     where (num % 2) == 0
     select num).ToArray();

Możesz również wymusić wykonywanie, umieszczając pętlę foreach bezpośrednio po wyrażeniu zapytania.You can also force execution by putting the foreach loop immediately after the query expression. Jednak przez wywołanie ToList lub ToArray można również buforować wszystkie dane w jednym obiekcie kolekcji.However, by calling ToList or ToArray you also cache all the data in a single collection object.

Zobacz takżeSee also