連載:[完全版]究極のC#プログラミング

Chapter17 LINQ to SQL

川俣 晶
2010/04/14

 本記事は、(株)技術評論社が発行する書籍『[完全版]究極のC#プログラミング ― 新スタイルによる実践的コーディング』から、許可を得て転載しています。
 同書籍は、もともと本フォーラムにて連載していた『C# 2.0入門』、『C# 3.0入門』の記事を整理統合し、加筆、修正されたものです。

手元でまとめて読みたい方は、ぜひ書店などにてお買い求めください。

 【注意】本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

17.1 効率的に列挙可能にするという問題

 前章でLINQ to Objectsの説明はおおむね終わったことになる。

 LINQ to Objectsは、列挙可能なオブジェクト、より正確にいえばIEnumerable<TSource>インターフェースを持つか、それに変換できるオブジェクトであれば、何もせずともクエリ(クエリ式、メソッド構文)を使用できる。クエリする対象データの種類も問われない。何らかの式を記述して比較可能なオブジェクトであれば、テキストであろうと画像であろうと検索できる。だから、問題は、いかにしてクエリを記述するかに絞られる。そのような観点で、ここまで説明してきた。

 しかし、これでLINQを征服したと思うのは早計である。というのは、それらはすべてLINQ to Objectsの話であって、それはLINQ世界の全貌ではないからだ。

 たとえば、何でも検索できることは、必ずしも最善の検索が可能であることを意味しない。それは、次ページの図17.1図17.2の2つの例を比較するとわかるだろう。

 オブジェクトに格納されていたら何でも検索できる、ということは、逆にいえば、検索するためにはオブジェクトに格納しなければならないことを意味する。また、ローカルに目的のデータが存在しない場合はそれらをすべてローカルに転送する処理も必要とされる。たとえば100万件のデータから1件のデータを探す場合、検索を行うごとに遠隔地のサーバーから100万件のデータを送らせ、それらをすべてオブジェクトに格納するのはあまりにも非効率的でありすぎる。通信回線、メモリ、CPUなどの負担が増えすぎ、プログラム動作の快適さも損なうことになるだろう。

 このような場合は、データのある場所に検索依頼を行うほうがよい。データのある場所であるがままのデータを検索してもらえば、データを転送する手間とオブジェクトに格納する手間がなくなり、きわめて効率が高くなる。

図17.1 非効率なお宝探し

図17.2 効率的なお宝探し

 実際、現在の主要なデータベースは、このような「検索依頼」によって成立しているといっても過言ではない。初期のパソコン用データベースにはファイル共有型など非効率なものもあったが、いまやそれらは主要なスタイルではない。

 とすれば、次の問題は、このような検索依頼をLINQ to Objectsが処理できないことである。この場合、検索対象は「列挙できるもの」ではない(そもそも、ローカルのオブジェクトですらない)ので、LINQ to Objectsでは手も足も出ないのである。

 この問題に対処するためには、LINQ to Objectsとは別のLINQプロバイダーを用意する必要がある。たとえば、LINQ to SQLはSQLサーバーに検索を依頼するためのLINQプロバイダーである。これはまさに、遠隔地への検索依頼として成立する。

 さて、クエリが遠隔地で実行されるとなると問題になるのが、クエリの中に書き込んだラムダ式の扱いである。たとえば、次のようなクエリ式の中の「n.from == "新宿"」という条件式は、遠隔地で実行されなければならない。

from n in 移動経路データ where n.from == "新宿" select n

 このような問題は、実は「付録2 .NET Framework 3.5の新機能―式ツリー」で紹介している「式ツリー」によって対処可能となる。このクエリ式は次のように置き換えられる。

移動経路データ.Where((n) => n.from == "新宿").Select((n) => n))

 そして、付録2で紹介している「式本体を持つラムダ式は、式ツリーに変換できる」という機能により、式本体を持つラムダ式である「(n) => n.from == "新宿"」は式ツリーに変換できる。式ツリーそのものは、木構造になったオブジェクトの集まりなので、遠隔地にデータとして容易に送信できる。あるいは、何らかの実行文に変換したうえで送信することもできる。それを受信側で解釈できれば、このクエリはそのまま遠隔地で実行可能となる

 C# 3.0で拡張されたさまざまな機能は、実はこのように相互に連携して大きな仕事をこなすように用意されたものなのである。

 LINQプロバイダーの実装は専門性が高く、かつ、それを行う必要に迫られる人はあまり多くないと思われるので、以下の2つのリンクを参考までに示して、これで終わることにする。本章の本題はプロバイダーの実装ではなくLINQ to SQLである。

クエリ式パターン
http://msdn.microsoft.com/ja-jp/library/bb308966.aspx#topic19

チュートリアル:IQueryable LINQプロバイダの作成
http://msdn.microsoft.com/ja-jp/library/bb546158.aspx


 INDEX
  [完全版]究極のC#プログラミング
  Chapter17 LINQ to SQL
  1.17.1 効率的に列挙可能にするという問題
    2.17.2 SQL Serverのワナ
    3.17.3 LINQ to SQLという突破口
    4.17.4 LINQ to SQLのサンプル
    5.17.5 LINQ to SQLとメソッド構文
    6.17.6 LINQ to SQLのまとめ/練習問題
 
インデックス・ページヘ  「[完全版]究極のC#プログラミング」


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 記事ランキング

本日 月間