クエリは、データ ソースからデータを取得する式です。 クエリは通常、リレーショナル データベースの SQL や XML 用の XQuery など、特殊なクエリ言語で表されます。 そのため、開発者は、クエリを実行するデータ ソースまたはデータ形式の種類ごとに新しいクエリ言語を学習する必要がありました。 Language-Integrated クエリ (LINQ) は、さまざまな種類のデータ ソースと形式でデータを操作するための、よりシンプルで一貫性のあるモデルを提供します。 LINQ クエリでは、常にプログラミング オブジェクトを操作します。
LINQ クエリ操作は、データ ソースまたはソースの取得、クエリの作成、クエリの実行の 3 つのアクションで構成されます。
IEnumerable<T>ジェネリック インターフェイスを実装するデータ ソースは、LINQ を使用して照会できます。 AsEnumerableでDataTableを呼び出すと、LINQ to DataSet クエリのデータ ソースとして機能するジェネリック IEnumerable<T> インターフェイスを実装するオブジェクトが返されます。
クエリでは、データ ソースから取得する情報を正確に指定します。 クエリでは、情報を返す前に並べ替え、グループ化、および整形する方法を指定することもできます。 LINQ では、クエリは変数に格納されます。 クエリが一連の値を返すように設計されている場合、クエリ変数自体は列挙可能な型である必要があります。 このクエリ変数はアクションを実行せず、データを返しません。クエリ情報のみが格納されます。 クエリを作成したら、そのクエリを実行してデータを取得する必要があります。
一連の値を返すクエリでは、クエリ変数自体はクエリ結果を保持することはなく、クエリ コマンドのみを格納します。 クエリの実行は、クエリ変数が foreach
ループまたは For Each
ループで反復処理されるまで遅延されます。 これは 遅延実行と呼ばれます。つまり、クエリの実行は、クエリが構築されてからしばらくしてから発生します。 つまり、必要な頻度でクエリを実行できます。 これは、たとえば、他のアプリケーションによって更新されるデータベースがある場合に便利です。 アプリケーションでは、最新の情報を取得してクエリを繰り返し実行するクエリを作成し、毎回更新された情報を返すことができます。
一連の値を返す遅延クエリとは対照的に、シングルトン値を返すクエリは直ちに実行されます。 シングルトン クエリの例としては、 Count、 Max、 Average、 Firstがあります。 これらは、シングルトンの結果を計算するためにクエリ結果が必要であるため、すぐに実行されます。 たとえば、クエリ結果の平均を検索するには、平均化関数に操作する入力データが含まれるようにクエリを実行する必要があります。 また、クエリで ToList メソッドまたは ToArray メソッドを使用して、シングルトン値を生成しないクエリを強制的に即時に実行することもできます。 即時実行を強制するこの手法は、クエリの結果をキャッシュする場合などに使用すると効果的です。
クエリ
LINQ to DataSet クエリは、クエリ式の構文とメソッドベースのクエリ構文という 2 つの異なる構文で作成できます。
クエリ式の構文
クエリ式は宣言型クエリ構文です。 この構文を使用すると、開発者は SQL のような形式で C# または Visual Basic でクエリを記述できます。 クエリ式の構文を使用すると、最小限のコードでデータ ソースに対して複雑なフィルター処理、順序付け、およびグループ化操作を実行できます。 詳細については、「 LINQ クエリ式 」と「 基本的なクエリ操作 (Visual Basic)」を参照してください。
.NET Framework 共通言語ランタイム (CLR) は、クエリ式の構文自体を読み取ることができません。 したがって、コンパイル時に、クエリ式は CLR が理解しているメソッド呼び出しに変換されます。 これらのメソッドは、 標準クエリ演算子と呼ばれます。 開発者は、クエリ構文を使用する代わりに、メソッド構文を使用して直接呼び出すオプションがあります。 詳細については、「LINQ の クエリ構文とメソッド構文」を参照してください。 標準クエリ演算子の詳細については、「標準クエリ演算子の 概要」を参照してください。
次の例では、 Select を使用してテーブルからすべての行 Product
返し、製品名を表示します。
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> query =
from product in products.AsEnumerable()
select product;
Console.WriteLine("Product Names:");
foreach (DataRow p in query)
{
Console.WriteLine(p.Field<string>("Name"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = From product In products.AsEnumerable() _
Select product
Console.WriteLine("Product Names:")
For Each p In query
Console.WriteLine(p.Field(Of String)("Name"))
Next
Method-Based クエリ構文
LINQ to DataSet クエリを作成するもう 1 つの方法は、メソッドベースのクエリを使用することです。 メソッド ベースのクエリ構文は、LINQ 演算子メソッドに対するダイレクト メソッド呼び出しのシーケンスであり、ラムダ式をパラメーターとして渡します。 詳細については、「 ラムダ式」を参照してください。
この例では、 Select を使用して、 Product
からすべての行を返し、製品名を表示します。
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
var query = products.AsEnumerable().
Select(product => new
{
ProductName = product.Field<string>("Name"),
ProductNumber = product.Field<string>("ProductNumber"),
Price = product.Field<decimal>("ListPrice")
});
Console.WriteLine("Product Info:");
foreach (var productInfo in query)
{
Console.WriteLine($"Product name: {productInfo.ProductName} Product number: {productInfo.ProductNumber} List price: ${productInfo.Price} ");
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = products.AsEnumerable() _
.Select(Function(product As DataRow) New With _
{ _
.ProductName = product.Field(Of String)("Name"), _
.ProductNumber = product.Field(Of String)("ProductNumber"), _
.Price = product.Field(Of Decimal)("ListPrice") _
})
Console.WriteLine("Product Info:")
For Each product In query
Console.Write("Product name: " & product.ProductName)
Console.Write("Product number: " & product.ProductNumber)
Console.WriteLine("List price: $ " & product.Price)
Next
クエリの作成
このトピックで前述したように、クエリ変数自体は、クエリが一連の値を返すように設計されている場合にのみクエリ コマンドを格納します。 クエリに即時実行を引き起こすメソッドが含まれていない場合、クエリの実際の実行は、 foreach
ループまたは For Each
ループ内のクエリ変数を反復処理するまで延期されます。 遅延実行を使用すると、複数のクエリを組み合わせたり、1 つのクエリを拡張したりできます。 クエリが拡張されると、新しい操作を含むように変更され、最終的な実行には変更が反映されます。 次の例では、最初のクエリはすべての製品を返します。 2 番目のクエリは、サイズ "L" のすべての製品を返す Where
を使用して、最初のクエリを拡張します。
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> productsQuery =
from product in products.AsEnumerable()
select product;
IEnumerable<DataRow> largeProducts =
productsQuery.Where(p => p.Field<string>("Size") == "L");
Console.WriteLine("Products of size 'L':");
foreach (DataRow product in largeProducts)
{
Console.WriteLine(product.Field<string>("Name"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim productsQuery = From product In products.AsEnumerable() _
Select product
Dim largeProducts = _
productsQuery.Where(Function(p) p.Field(Of String)("Size") = "L")
Console.WriteLine("Products of size 'L':")
For Each product In largeProducts
Console.WriteLine(product.Field(Of String)("Name"))
Next
クエリの実行後、追加のクエリを作成することはできなくなり、それ以降のすべてのクエリではメモリ内 LINQ 演算子が使用されます。 クエリの実行は、 foreach
ステートメントまたは For Each
ステートメント内のクエリ変数を反復処理するとき、または直ちに実行される LINQ 変換演算子の 1 つを呼び出すと発生します。 これらの演算子には、 ToList、 ToArray、 ToLookup、および ToDictionaryが含まれます。
次の例では、最初のクエリは定価順のすべての製品を返します。 ToArray メソッドは、クエリの即時実行を強制するために使用されます。
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> query =
from product in products.AsEnumerable()
orderby product.Field<Decimal>("ListPrice") descending
select product;
// Force immediate execution of the query.
IEnumerable<DataRow> productsArray = query.ToArray();
Console.WriteLine("Every price from highest to lowest:");
foreach (DataRow prod in productsArray)
{
Console.WriteLine(prod.Field<Decimal>("ListPrice"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = _
From product In products.AsEnumerable() _
Order By product.Field(Of Decimal)("ListPrice") Descending _
Select product
' Force immediate execution of the query.
Dim productsArray = query.ToArray()
Console.WriteLine("Every price From highest to lowest:")
For Each prod In productsArray
Console.WriteLine(prod.Field(Of Decimal)("ListPrice"))
Next