特集:VBプログラマーのためのLINQ超入門(前編)

LINQ(リンク)の基礎知識

デジタルアドバンテージ 遠藤 孝信
2008/09/26
Page1 Page2 Page3 Page4

クエリの実行を支えるさまざまなLINQプロバイダ

 このように、LINQはデータベースだけでなく、同じ構文でコレクションや配列にも使えます。これら以外にも、XMLデータやADO.NETのデータセット(DataSet)などに対しても利用できます。LINQの構文は、どれに対してもすべて同じです。

 想像するに「VBからSQL文を発行するときにはそれを文字列として記述しなければならず不便。思い切って言語に取り込んでみては? そうだ、そうすれば同じ記述でコレクションやXMLにも使えて便利だぞ!」といった感じでしょうか。

 しかしもちろん、実行時の処理は、例えばデータベースとコレクションとではまったく異なります。データベースの場合には、クエリからSQL文を生成してデータベース・サーバへ送信する仕組みが必要になりますから。

 LINQでは、問い合わせ先であるデータソース(「From n In XXX」のXXXの部分。これについてはすぐ次で解説しています)の型に基づいて、クエリがどのようにコンパイルされ、実行されるのかが決まる仕組みになっています。端的にいえば、最終的に問い合わせ処理の実行を担当するクラス(通常はクラス群)がクエリ対象の種類によって異なるというわけです。

 このようなデータソースの種類ごとに存在する一連のクラス群は「LINQプロバイダ」と呼ばれます(プロバイダとは、各データソースに対する「ドライバ」であるといった方が分かりやすいかもしれません)。

 ADO.NETではデータ・プロバイダをSQL Server用やOracle用に切り替えるだけで、同じコードで異なるデータベース・システムにアクセスできる仕組みになっていました。同様にLINQでは、LINQプロバイダを切り替えることにより、同じクエリ構文でさまざまな対象を検索できるようになっています。上述したように、使用されるLINQプロバイダはクエリ対象によって決まります。

 .NET Framework 3.5では、標準で次の図に示すようなLINQプロバイダが用意されています。


.NET Framework 3.5で用意されているLINQプロバイダ

 例えば、先ほどのリスト2やリスト3のように、LINQによりデータベースを検索するときには「LINQ to SQL」の機能を利用していることになります。また、リスト5の配列への問い合わせは「LINT to Object」の機能です。

 また、「LINQ to DataSet」はADO.NETのデータセットに対して、「LINQ to XML」はXMLデータに対してLINQを実行可能にするためのLINQプロバイダです。

 データセットはデータベースから取得した結果を格納するためのADO.NETの仕組みですが、そこに格納されたデータの検索に関してはSelectメソッド*1ぐらいしか手段が用意されていませんでした。またXMLに関しては、特定の要素を取得するのにXPathやXQueryといった機能を使うのが標準的でした。LINQをマスターしていれば、これらのデータも同じLINQの構文で統一的に扱えることになります。

*1 データセット内に含まれるデータテーブルのSelectメソッド。

 もちろん、ADO.NETのデータ・プロバイダと同様に、独自のLINQプロバイダ(LINQ to XXX)を作成することも可能です。そのためのフレームワークはクラス・ライブラリに用意されています。すでに、「LINQ to Amazon」「LINQ to Excel」「LINQ to Flickr」「LINQ to Google」といったLINQプロバイダが作成されているようです*2

*2Links to LINQ」にまとめページがありました。

LINQで使用するキーワード

 LINQによるクエリの書き方をもう少し詳しく見ていきましょう。

From n In data _
Where n.ShipCountry = "Norway" _
Select n
リスト6 リスト5から抜粋したLINQによるクエリ

 LINQのクエリは基本的に「From句」で始まり、「Select句」で終わります。ここで登場している「From句(From 〜 In 〜)」「Where句」「Select句」は、クエリ用のVB 9.0の新しいキーワードです。

 VB 9.0では、このようなクエリ用のキーワードとして、主に以下のようなものが用意されています。

キーワード 機能
From データソースおよび範囲変数を指定する
Where フィルタ条件を指定する
Select クエリ結果の要素の形式を指定する
Group By 指定したキーによりクエリ結果をグループ化する
Order By クエリ結果をソートする
Join 2つのデータソースを結合する
Let 新しい範囲変数を作成する
表1 LINQで使用するクエリ用の主要なキーワード
各キーワードの正確な形式や詳細はそれぞれのリンクからオンライン・リファレンスを参照してほしい。VB 9.0では、C# 3.0に比べて、集計関数をクエリに含めるためのAggregate、クエリ結果のN件目からM件分を取り出すSkipTakeなども言語の一部として実装されているという特徴がある。

 ここでは、リスト6で使っているFrom、Where、Selectについて説明します。

■From句

 まず、From句は、

From <範囲変数> In <データソース>

の形式で記述します。

 <データソース>にはLINQによる問い合わせの対象を指定します。ここには、IEnumerable(Of T)インターフェイス(あるいはIEnumerableインターフェイス、あるいはそれらの派生インターフェイス)を実装したオブジェクトが指定できます。このインターフェイスを実装しているオブジェクトは、列挙可能なコレクションです。これは簡単にいってしまえば、For Eachループが使えるオブジェクトです。

 例えば、List(Of Integer)クラスはInteger型オブジェクトのリストですが、List(Of T)クラスはIEnumerable(Of T)インターフェイスを実装していますので、LINQが使えます。また、配列やArrayListクラスはIEnumerableインターフェイスを実装していますのでLINQが使えます。

 <範囲変数>(range variable)では、データソース内の各要素を入れる変数を指定します。データソースがIEnumerable(Of T)インターフェイスを実装していれば、範囲変数の型は自明ですので(データソースがList(Of Integer)型なら範囲変数はInteger型)、範囲変数の型指定は省略できます*3

*3データソースにArrayListオブジェクトを指定した場合、範囲変数には要素の型を指定する必要があります。

■Where句とSelect句

 Where句ではフィルタとなる条件式を記述します。条件式は真(True)あるいは偽(False)となる式です。複数の条件を記述する場合には「And」や「Or」を使います。VBの条件式と似ていますが、実はWhere句に記述する条件式はVBの条件式そのものです。ここで指定した式が具体的にどのような形で利用されるかについては、後編で説明します。

 一方、Select句では、クエリの戻り値となる形式を指定します。ここでの型によってクエリ結果の型が決まります。リスト6では「Select n」としていますので、範囲変数nをそのままの形で出力します。従って、範囲変数がOrders型であれば、クエリ結果はIEnumerable(Of Orders)型となります。リスト6で、もし「Select n.ShipCountry」とした場合には、クエリ結果はIEnumerable(Of String)型となります。

 VB 9.0の新しい機能である「匿名型」を使えば、複数の項目を一時的に集めて1つのオブジェクトとしてまとめることもできますが、これについても後編で解説します。ちなみにこの場合には、クエリ結果を代入する変数は“As句なしのDimステートメント”を使って宣言する必要があります。

■LINQの標準クエリ演算子

 Where句やSelect句といったLINQのキーワードは、実はコンパイラによりメソッドの呼び出しに変換されます。例えば、Where句は「Whereメソッド」、Select句は「Selectメソッド」の呼び出しになります。

 これらのメソッドは、System.Linq名前空間のEnumerableクラスで定義されています(LINQ to Objectの場合)。このクラスには約50個の静的メソッドが定義されていますが、これらのメソッドは「標準クエリ演算子(Standard Query Operator)」と呼ばれ、LINQのクエリを記述するために用意されています。

 標準クエリ演算子のメソッドすべてに、VB 9.0のキーワードが対応しているわけではありませんので、実際には表1のキーワードと標準クエリ演算子のメソッドを混在させてクエリを記述することになります。

 あるいは表1のキーワードをまったく使用しないで、すべてメソッド呼び出しでクエリを記述することもできます。後編ではクエリがどのようにメソッドに置き換えられるかについて解説しています。


 INDEX
  VBプログラマーのためのLINQ超入門(前編)
  LINQ(リンク)の基礎知識
    1.ADO.NET+SQL文によるデータベースへの問い合わせ
    2.LINQによるデータベース/コレクションへの問い合わせ
  3.クエリの実行を支えるさまざまなLINQプロバイダ/LINQの書き方
    4.そのほかのポイント/LINQPadの紹介
 
  VBプログラマーのためのLINQ超入門(後編)
  LINQによるデータベース・アクセスとO/Rマッピング
    1.LINQのメソッド構文
    2.データベースの問い合わせを行うLINQ to SQL
    3.O/RマッピングとLINQ to SQL


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間