CodeZine(コードジン)

特集ページ一覧

統合言語クエリ(LINQ/Language Integrated Query)入門

LINQのクエリ式を利用する

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/10/02 14:00

 LINQの概要とLINQに関する誤解について取り上げ、そのベースとなる言語機能を簡単におさらいしてから、LINQを使用した例をいくつか説明します。

目次

はじめに

 .NET入門コラムの連載記事にようこそ。今回は、Language Integrated Query、略してLINQを中心に紹介します。LINQの概要とLINQに関する誤解について取り上げ、そのベースとなる言語機能を簡単におさらいしてから、LINQを使用した例をいくつか説明します。今後の連載ではLINQを何度か取り上げる予定ですが、今回がその第1弾です。

Language INtegrated Queryの概要

 これまでの.NET入門コラムの記事の多くは、私が最初に書いたいくつかの記事(「Database Independent Data Access」など)までさかのぼって考えてみても、必ずと言っていいほどデータへのアクセスと処理を話題にしていました。一般に、データはデータベースに格納されますが、データにアクセスして処理する方法には、データファイル、イベントログ、Windowsのレジストリなど、他にもさまざまな形態があります。データのクエリと処理は、多くのアプリケーションに共通する要素です。

 LINQ(発音は「リンク」)とは、データへのアクセスに進化をもたらす第一歩となるものです。これは、必要とされる統一性をデータアクセスに与えるプログラミングモデルであり、その対象はファイル、XML、データベース、レジストリ、イベントログから、アクティブディレクトリなどの多種多様なデータソース、さらにはFlickrなどのサードパーティ製サービスにまでおよびます。あらゆる形態のさまざまなサイズのデータを取り扱い、そのすべてに対してクエリ、設定、変換の各操作を実行できるように設計されています。IEnumerable型を実装することそのものが、LINQの目的でもあります。

LINQに関する誤解

 何かを理解しようとするときに役立つ1つのパターンは、「その対象が何であるか」の逆、つまり「その対象が何でないか」について考えることです。誰かに初めてLINQを紹介しようとするときに最もよく使われるのが、「LINQとは単なる組み込みSQLである」という表現ですが、これは正しくありません。LINQの構文は、その多くがSQLによく似た構造をしていますが、単なる組み込みSQLではありませんし、データベースへのクエリに限られたものでもありません。LINQはすべての.NET言語で無条件にサポートされるものではありません。共通言語ランタイム(CLR)に対しては、何の変更も行われていません。変更が加えられたのは、各言語とそれぞれのコンパイラのみです。このとき、言語固有の拡張が多少必要となり、Visual Basic .NET 9.0とC# 3.0には、LINQ用の統合言語サポートが組み込まれました。

LINQを実現する言語機能

 LINQでは、ジェネリックを多用します。また、Visual BasicとC#の各言語には、LINQをサポートする専用の機能が多数追加されました。私の最近の記事でも、LINQに先行してこうした言語機能の一部を何度か紹介しています。次のリストは、LINQの実現に寄与する言語機能の一部と、各機能の簡単な説明です。

  • 型推論 ― コンパイル時に、(式の)右辺に割り当てられた型が変数型となる簡略表現です。
  • 拡張メソッド ― 新しい型を派生することなく、既存の値型または参照型を拡張できます。
  • オブジェクト初期化子 ― オブジェクト初期化構文の短縮形で、等価なコードを生成できます。
  • 匿名型 ― メソッドや型を生成せずに文を作成することができます。
  • ラムダ式 ― インラインメソッドを簡潔に記述する方法です。
  • クエリ式 ― オブジェクトを処理するコードの中に書かれるSQLライクな文です。

 これらの言語機能は、機能自体に何らかのメリットがあることは確かです。しかし私見としては、これらの機能の多くはLINQ以外で使用する理由が見当たりません。

LINQの種類

 さまざまなデータソースにアクセスして処理を行うため、LINQにはいくつかの種類があります。次のリストでは、Microsoftから提供されているデータドメインの一部を挙げました。今後、.NET入門ではこの中のいくつかを取り上げる予定です。

  • LINQ to Objects ― オブジェクトのコレクションを操作
  • LINQ to DataSets ― LINQを使用してDataSetを操作
  • LINQ to SQL ― カスタム型オブジェクトと物理データベーステーブルのスキーマをマッピング
  • LINQ to Entities ― 概念的なエンティティデータモデルを使用して物理データベースの概念モデルを作成
  • LINQ to XML ― XMLのクエリと処理を実現

LINQ構文の概要

 コードの構造と書式に大きなこだわりのある人の場合は、LINQの構文に馴染んで自分のコードに取り入れるまでに少し時間がかかるかもしれません。同様に、SQLクエリをコードに埋め込まないようにとお決まりの呪文を何度も聞かされている人も、LINQを使用することが実は悪いことでもやましいことでもなく、むしろその正反対であると納得するまでには時間を要するでしょう。

 LINQがデータベースへのアクセスに限定されたものでないことは確かです。ただ、LINQを理解してもらうには、最初にSQL文を検討した後、同じ内容をコードに埋め込まれたLINQへと書き直して説明するのが一番分かりやすいでしょう。次のSQL文は、Microsoft SQL Serverに共通なサンプルデータベースNorthwindに対して作成したものです。このクエリは、所在が「Berlin」ではない顧客のリストを取得するだけの基本的なクエリです。

SELECT c.CompanyName, c.ContactName, c.City
FROM Customers c
WHERE c.City != 'color:red'>'Berlin'
ORDER BY c.ContactName

 それでは、このSQL文をLINQで書き直して、細部まで理解するために詳しく検討しましょう。クエリの構文には、クエリ式とメソッドクエリの2種類があります。ここでは、クエリ式に着目します。次のクエリ式では、GetCustomers()から返されるIEnumerable型を検索して、「City」の場所が「Berlin」ではないデータを取り出しています。この例の場合、GetCustomersメソッドがデータベースにアクセスして、IEnumerable型を返すと考えられます。

var customerNotInBerlin =
   from c in GetCustomers()
   where c.City != "Berlin"
   orderby c.ContactName
   select c;

 次の表は、LINQの構文に用意されているオプションの一部をまとめたものです。

格納先 var <変数> = 取得した値の割り当てに型推論を使用
ソース from <項目> in <データソース> 項目セットを取得する情報ソース
フィルタ where <式>、distinct 選択条件を指定する式
順序 order by <式>, <式> [Ascending | Descending] 結果の順序付け制御
集計 count([<式>])、sum(<式>)、min(<式>)、max(<式>)、avg(<式>) ソース項目の集計
射影 select <式> 出力の生成

 上記の項目以外にも、たくさんのオプションとバリエーションが構文に存在しますが、理解するための出発点としてはこれで十分です。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

あなたにオススメ

著者プロフィール

  • japan.internet.com(ジャパンインターネットコム)

    japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.com や EarthWeb.c...

  • Mark Strawmyer(Mark Strawmyer)

     大企業および中規模企業向け.NETアプリケーションの開発に携わるシニアアーキテクト。インディアナ州インディアナポリスにあるCrowe Chizekでテクノロジリーダーを務め、Microsoftのソリューションをベースとしたアーキテクチャ、設計および開発を専門とする。C#によるアプリケーション開発で...

バックナンバー

連載:japan.internet.com翻訳記事

もっと読む

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5