LINQ クエリの概要 (C#)Introduction to LINQ Queries (C#)

"クエリ" は、データ ソースからデータを取得する式です。A query is an expression that retrieves data from a data source. クエリは通常、専用のクエリ言語で表されます。Queries are usually expressed in a specialized query language. これまでに、リレーショナル データベース用の SQL や XML 用の XQuery など、データ ソースの種類に合わせてさまざまな言語が開発されてきました。Different languages have been developed over time for the various types of data sources, for example SQL for relational databases and XQuery for XML. このため、開発者は、サポートする必要のあるデータ ソースの種類やデータ形式ごとに、新しいクエリ言語を習得する必要がありました。Therefore, developers have had to learn a new query language for each type of data source or data format that they must support. LINQLINQ は、さまざまな種類のデータ ソースやデータ形式のデータを操作するための一貫したモデルを提供することにより、この負担を軽減します。simplifies this situation by offering a consistent model for working with data across various kinds of data sources and formats. LINQLINQ クエリでは、操作の対象は常にオブジェクトになります。In a LINQLINQ query, you are always working with objects. 共通の基本的なコーディング パターンを使用することで、LINQLINQ プロバイダーを利用できる XML ドキュメント、SQL データベース、ADO.NET データセット、.NET コレクション、その他の任意の形式のデータを照会したり変換したりできます。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.

クエリ操作の 3 つの手順Three Parts of a Query Operation

すべての LINQLINQ クエリ操作は、次の 3 つの手順で構成されます。All LINQLINQ query operations consist of three distinct actions:

  1. データ ソースを取得します。Obtain the data source.

  2. クエリを作成します。Create the query.

  3. クエリを実行します。Execute the query.

クエリ操作の 3 つの手順がソース コードでどのように表されるかを次の例に示します。The following example shows how the three parts of a query operation are expressed in source code. この例では、わかりやすくするために整数の配列をデータ ソースとして使用していますが、他のデータ ソースを使用する場合にも同じ概念が当てはまります。The example uses an integer array as a data source for convenience; however, the same concepts apply to other data sources also. このコードは、このトピックの残りの部分全体を通して参照されます。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);
        }
    }
}

次の図は、クエリ操作全体を表しています。The following illustration shows the complete query operation. LINQLINQ では、クエリの実行はクエリ自体とは別個のものです。つまり、クエリ変数を作成するだけでは、データは取得されません。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.

完全な LINQ クエリ操作の図。

データ ソースThe Data Source

前の例では、データ ソースが配列であるため、暗黙的にジェネリック IEnumerable<T> インターフェイスがサポートされます。In the previous example, because the data source is an array, it implicitly supports the generic IEnumerable<T> interface. つまり、LINQLINQ でクエリを実行できるということです。This fact means it can be queried with LINQLINQ. クエリは foreach ステートメントで実行されますが、foreach には IEnumerable または IEnumerable<T> が必要です。A query is executed in a foreach statement, and foreach requires IEnumerable or IEnumerable<T>. IEnumerable<T> をサポートする型や、ジェネリック IQueryable<T> などの派生インターフェイスは、クエリ可能型と呼ばれます。Types that support IEnumerable<T> or a derived interface such as the generic IQueryable<T> are called queryable types.

クエリ可能型は、変更や特別な処理を行わなくても、LINQLINQ データ ソースとして使用できます。A queryable type requires no modification or special treatment to serve as a LINQLINQ data source. ソース データがメモリ内にクエリ可能型として存在していない場合、LINQLINQ プロバイダーは、そのような型としてソース データを表す必要があります。If the source data is not already in memory as a queryable type, the LINQLINQ provider must represent it as such. たとえば、LINQ to XMLLINQ to XML では、クエリ可能な XElement 型に XML ドキュメントが読み込まれます。For example, LINQ to 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");

LINQ to SQLLINQ to SQL では、まず、デザイン時に手動で、または Visual Studio で LINQ to SQL ツールを使用して、オブジェクト リレーショナル マッピングを作成します。With LINQ to 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. オブジェクトに対するクエリを記述すると、実行時には、LINQ to SQLLINQ to SQL によってデータベースとの通信が処理されます。You write your queries against the objects, and at run-time LINQ to SQLLINQ to SQL handles the communication with the database. 次の例では、Customers がデータベース内の特定のテーブルを表し、クエリ結果の型 IQueryable<T>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;  

それぞれの種類のデータ ソースを作成する方法の詳細については、対応する LINQLINQ プロバイダーのドキュメントを参照してください。For more information about how to create specific types of data sources, see the documentation for the various LINQLINQ providers. ただし、基本的な規則は非常に単純です。LINQLINQ データ ソースは、ジェネリック IEnumerable<T> インターフェイス、またはこれを継承するインターフェイスをサポートする任意のオブジェクトです。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.

注意

非ジェネリック ArrayList インターフェイスをサポートする IEnumerable などの型も、LINQLINQ データ ソースとして使用できます。Types such as ArrayList that support the non-generic IEnumerable interface can also be used as a LINQLINQ data source. 詳細については、「方法 :LINQ を使用して ArrayList を照会する (C#)For more information, see How to: Query an ArrayList with LINQ (C#).

クエリThe Query

クエリでは、データ ソースからどのような情報を取得するかを指定します。The query specifies what information to retrieve from the data source or sources. オプションとして、情報が返される前に、その情報を並べ替え、グループ化し、構造化する方法を指定することもできます。Optionally, a query also specifies how that information should be sorted, grouped, and shaped before it is returned. クエリはクエリ変数に格納され、クエリ式で初期化されます。A query is stored in a query variable and initialized with a query expression. クエリを簡単に記述できるようにするために、C# に新しいクエリ構文が導入されています。To make it easier to write queries, C# has introduced new query syntax.

前の例のクエリでは、整数の配列からすべての偶数が返されます。The query in the previous example returns all the even numbers from the integer array. クエリ式には、fromwhere、および select の 3 つの句が含まれています The query expression contains three clauses: from, where and select. (SQL に詳しい方は、句の順番が SQL での順番とは逆になっていることに気付かれると思います)。from 句はデータ ソースを指定し、where 句はフィルターを適用し、select 句は返される要素の種類を指定します。(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. これらのクエリ句およびその他のクエリ句の詳細については、「LINQ クエリ式」セクションで説明しています。These and the other query clauses are discussed in detail in the LINQ Query Expressions section. 今の段階で重要な点は、LINQLINQ では、クエリ変数自体は何も処理を行わず、データを返さないという点です。For now, the important point is that in LINQLINQ, the query variable itself takes no action and returns no data. この時点では、後でクエリが実行されるときに結果の生成に必要となる情報が格納されるだけです。It just stores the information that is required to produce the results when the query is executed at some later point. 背後でどのようにクエリが構築されるかについては、「標準クエリ演算子の概要 (C#)」をご覧ください。For more information about how queries are constructed behind the scenes, see Standard Query Operators Overview (C#).

注意

クエリは、メソッド構文を使用して表すこともできます。Queries can also be expressed by using method syntax. 詳細については、「LINQ でのクエリ構文とメソッド構文」を参照してください。For more information, see Query Syntax and Method Syntax in LINQ.

クエリの実行Query Execution

遅延実行Deferred Execution

先に説明したように、クエリ変数自体が行うのはクエリ コマンドの格納のみです。As stated previously, the query variable itself only stores the query commands. 実際のクエリの実行は、foreach ステートメントでクエリ変数が反復処理されるまで延期されます。The actual execution of the query is deferred until you iterate over the query variable in a foreach statement. この概念を "遅延実行" と呼びます。遅延実行の例を次に示します。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);
}

foreach ステートメントでは、クエリ結果の取得も行われます。The foreach statement is also where the query results are retrieved. たとえば、前のクエリでは、返されるシーケンスの各値が反復変数 num に (一度に 1 つずつ) 格納されます。For example, in the previous query, the iteration variable num holds each value (one at a time) in the returned sequence.

クエリ変数自体にはクエリ結果は格納されないので、必要に応じて何度でもクエリを実行できます。Because the query variable itself never holds the query results, you can execute it as often as you like. たとえば、別のアプリケーションによって頻繁に更新されるデータベースがあるとします。For example, you may have a database that is being updated continually by a separate application. 自分のアプリケーションでは、最新のデータを取得するクエリを 1 つ作成し、それを一定の間隔で繰り返し実行することで、毎回異なる結果を取得できます。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.

即時実行の強制Forcing Immediate Execution

一連のソース要素に対して集計関数を実行するクエリでは、最初にそれらの要素を反復処理する必要があります。Queries that perform aggregation functions over a range of source elements must first iterate over those elements. このようなクエリには、CountMaxAverageFirst などがあります。Examples of such queries are Count, Max, Average, and First. これらのクエリでは、明示的に foreach ステートメントを使用しなくても同等の処理が実行されます。これは、結果を返すためにクエリ自体が foreach を使用する必要があるからです。These execute without an explicit foreach statement because the query itself must use foreach in order to return a result. これらの種類のクエリでは、IEnumerable コレクションではなく、単一の値が返されることにも注意してください。Note also that these types of queries return a single value, not an IEnumerable collection. 次のクエリは、ソース配列に含まれている偶数の数を返します。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();

クエリの即時実行を強制し、その結果をキャッシュするには、ToList メソッドまたは 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();

クエリ式の直後に foreach ループを配置することでも実行を強制できます。You can also force execution by putting the foreach loop immediately after the query expression. ただし、ToList または ToArray を呼び出した場合は、単一のコレクション オブジェクトにすべてのデータをキャッシュする処理も行われます。However, by calling ToList or ToArray you also cache all the data in a single collection object.

関連項目See also