連載:[完全版]究極のC#プログラミングChapter17 LINQ to SQL川俣 晶2010/04/14 |
|
|
17.4 LINQ to SQLのサンプル
本書は、あくまでC# 3.0入門である。LINQ to SQLは、C# 3.0の外部に存在する独立した技術であり、Visual Basicなどでも利用されるものである。そのため、本書ではC# 3.0プログラマーとLINQ to SQLの関わりを示し、簡単なサンプルを提示する程度にとどめる。前者についてはすでに述べたので、あとは簡単なサンプルを1つだけ提示して終わろう。とはいえ、C#プログラマーとして見るべきところは多い。
ここでは、図17.3、図17.4のようなテーブルPointListが存在するという前提で始めよう。
図17.3 PointListテーブルの設計 |
以降では、このテーブルに含まれる、pointが80以上の人を検索してみよう。
まず、Visual Studio 2008でコンソールアプリケーションのプロジェクトを作成する。次に、このプロジェクトに「LINQ to SQLクラス」を追加する。これはテンプレートから選ぶだけなので簡単だろう。
図17.4 PointListテーブルの内容 |
追加すると即座にO/Rデザイナが開かれて、図17.5のような表示になる。
図17.5 LINQ to SQLクラス追加時に開くO/Rデザイナ |
これを使って、O/Rマッピングを作成してみよう。やり方は簡単で、サーバーエクスプローラ上の[PointList]という項目を中央の領域へドラッグ&ドロップするだけである(図17.6参照)。
これでコードを書く準備はできた。Program.csにリスト17.1のようなコードを書いてみよう。
図17.6 生成されたO/Rマッピング |
| |
リスト17.1 LINQ to SQLによるデータベースの検索 |
ここで、DataClasses1DataContextクラスはO/RマッピングとしてO/Rデザイナが自動生成してくれたクラス名である。これを使えば、db.PointListと書くだけでPointListテーブルに対するマッピングを参照でき、それはクエリ式でクエリできる。
ちなみに、ここでは「m.date.ToString("yyyy/MM/dd")」の部分に注目しよう。この書式指定付きToStringメソッドはDateTime構造体に固有のものである。このようなコードが記述可能であるのは、PointListテーブルのdate列がDateTime型のプロパティにマッピングされているからである。つまり、SQLの型とC#の型がマッピングによって連携しており、型に関するトラブルが飛躍的に起こりにくくなっている。
さて、ここで注意すべき点がある。このクエリ式は、実際にはC#プログラムとしては実行されていない点である。つまり、「n.point >= 80」という式は、C#プログラムとして実行されることはない。
常識的なC#プログラマーの感覚でいえば「そんなばかな」と思うかもしれないが、それは事実である。では、どのようにしてそれを証明できるだろうか?
その方法は簡単で、変数dbをnewしている行の次に、次に示した行を挿入するだけである。
|
これで、どのようなSQL文がSQL Serverに送信されているかが手に取るようにわかる。
| |
リスト17.1でSQL Serverに送信されているSQL文 |
この3行目は、pointが「@p0」以上である場合という条件を示し、4行目で、@p0は80であることが示されている。つまり、このクエリの中には「n.point >= 80」という条件そのものが埋め込まれ、SQL Server側で処理されているのである。
このことは、クエリがサーバー側で処理され、結果だけが返ってくることを示す。大量のデータをまず取得して検索を行うようなネットワークの無駄は排除されている。
一方で、このような仕掛けが成立する理由は、本章の冒頭でも説明したとおり、「式本体を持つラムダ式は、式ツリーに変換できる」というC# 3.0の機能にある。LINQのクエリ式を式ツリーに変換したうえで、それをさらにSQL文に翻訳しているわけである。
このことは、式ツリーに翻訳できてもSQL文に翻訳できない式は扱えないことを示す。たとえば、条件判定がローカル上のメソッドに依存するような式はSQL文に翻訳できない。SQL Server側に同等のメソッドが存在しないからである。
たとえば、Programクラスに次のメソッドを追加してみよう。
|
そして、クエリを次のように書き直してみよう。
|
このプログラムは構文的には正しいのでコンパイル可能である。しかし、実行すると次のような例外を出して止まる。
|
SQL Server側からはcheckメソッドは直接呼び出せないし、仮にネットワークを越えて呼び出したとしても、時間がかかりすぎてクエリ速度が非現実的に遅くなるだけだろう。
ただし、次のようなメソッドを用意した場合はクエリできる。
|
クエリは次のように記述する。
|
この場合、get80メソッドはローカル上で計算可能であり、その計算結果である「80」をサーバーへ送ることでクエリは成立する。
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#プログラミング」 |
- 第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用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|