Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

DB開発でありがちな悩みを解決! Visual Studioと組合せて便利なLINQメソッド式を使ってみよう

Visual StudioでDB連携も簡単プログラミング ~知っておきたいLINQメソッド式&ラムダ式 第2回

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

 本連載では、データベースプログラミングにおいてLINQをどのように活用できるのか、解説していきます。前回の記事では、LINQとラムダ式の概要と、クエリ対象のデータベースをEntity Framework Code Firstで準備するところまで解説しました。今回は実際にデータベースに対してLINQメソッド式を使ってクエリを実行してみましょう。ごく基本的なクエリとなりますが、LINQとラムダ式、そしてVisual Studioの組み合わせの強力さを垣間見ることができると思います。

目次

レコード全件取得

 まずは何もせず全件取得のケースから始めます。ここではまだLINQは使用していません。

リスト1 何もせずレコード一覧を出力 - CodeZineSampleContext.cs
using (var context = new CodeZineSampleContext()) //(1)コンテキストを生成
{
  IQueryable<Product> products = context.Products; //(2)全件取得
  DumpProducts(products); //(3)取得したエンティティを出力
}
・・・
//エンティティのダンプメソッド
private static void DumpProducts(IQueryable<Product> products)
{
    foreach (var product in products) //1件ずつ取り出して
    {
        //(4)商品(Products)、出荷元(Makers)、担当者(Employees)
        //  部署(Departments)の情報をダンプ
        Console.WriteLine(
          "Product Name: {0}, Price : {1}\n  Maker Name: {2}\n  Employee Name: {3}, Department: {4}",
          product.Name, product.Price, product.Maker.Name,
          product.Employee.Name, product.Employee.Department.Name);
    }
}

 (1)では、Entity Frameworkの作法に則ってコンテキストを生成しています。このコンテキストクラスから各テーブルへのクエリを行います。

 (2)では、コンテキストのProdcutsプロパティから、Productsテーブルの全件を取得しています。戻り値がIQueryable<Product>となっていますが、これは「データベースでクエリを実行し、結果として返ってくるProduct一覧」を指しています。

 (3)では、取得したProductエンティティ一覧を(4)のDumpProductsメソッドに投げて、データの内容を出力しています。

 (4)では、foreachで1件ずつ取り出したProductエンティティについて、商品(Products)、出荷元(Makers)、担当者(Employees)、部署(Departments)の情報をコンソールに出力しています。

 結果はリスト2のようになります。

リスト2 テーブル一覧の出力結果
Product Name: ショートケーキ, Price : 250
  Maker Name: お菓子屋さんA
  Employee Name: 土井, Department: 営業部
・・・

 なお、「Productsテーブルの全件取得しているはずなのに、他のテーブルの内容まで取り出せているのはなぜだろう?」という問いは、第3回まで取っておきましょう。じっくり考えたい良問です。

LINQメソッド式でデータベースクエリを書いてみよう

 ようやく本題のLINQメソッド式を使ったクエリまで来ました。

 まずは小手調べに、特定の金額未満の商品を出力してみます(リスト3)。

リスト3 特定の金額未満の商品
products = context.Products.Where(x => x.Price < 300);
DumpProducts(products);

 ここではWhereメソッドでフィルタしており、ラムダ式は「x => x.Price < 300」となっています。xのデータ型が指定されていませんが「context.ProductsはDbSet<Product>というProductのコレクションなので、一件ずつ取り出して処理するなら当然xはProductのはず」という型推論が働いています。したがって、「x.」と書いた時点で図1のようにProductのメンバがIntelliSense表示されます。

図1 ProductのメンバがIntelliSense表示される
図1 ProductのメンバがIntelliSense表示される

 また、ミスタイプすれば図2のようにエラー表示してくれます。

図2 ProductにTotalPriceプロパティは存在しないので赤波線でエラー表示
図2 ProductにTotalPriceプロパティは存在しないので赤波線でエラー表示

 このように、Entity FrameworkとLINQを使えば「データベースのフィールド名忘れちゃった。定義書どこだっけ……このフィールドのデータ型は何だっけ……」といったデータベース開発でありがちな悩みとは、すっきりおさらばできます。

文字列部分一致検索を書いてみる

 続いて、文字列部分一致検索の場合はリスト4のようになります。

リスト4 文字列部分一致検索
products = context.Products.Where(x => x.Employee.Name.Contains("土"));
DumpProducts(products);

 ここでは「土」という文字が担当者名に含まれている商品だけをフィルタしています。ラムダ式が少し複雑になっていますが、「Product(商品)->Employee(担当者)->Name(担当者名文字列)->string型のContainsメソッド」と流れています。別テーブル(Employees)のフィールドでの絞り込みも自由自在です。string型のContainsメソッドを使っていますが、これはデータベース上で「LIKE '%土%'」のようなSQLに変換されて実行されますので、文字列部分一致検索も簡単に書くことができます。「LIKE条件を%で挟むの忘れた……」なんてお約束のミスもおさらばです。

特定の値のいずれかに当てはまるものを検索する

 もう一つ、「特定の価格リストに当てはまるものだけ検索」も見てみましょう(リスト5)。

リスト5 特定の価格リストで検索
var list = new List<int>() { 100, 200, 300, 400, 500 };
products = context.Products.Where(x => list.Contains(x.Price));
DumpProducts(products);

 今回はあらかじめ金額をList<int>で定義しておき、ラムダ式の中では「list.Contains(x.Price)」として、「listの中にx.Priceが含まれているかどうか」という条件を書いています。これもデータベース上では「IN (100, 200, 300, ...)」というIN演算子を使ったSQLに変換されます。SQLを文字列連結で作る場合の「IN演算子の後に1個ずつカンマで挟んで出力しなきゃ。あ、末尾にカンマを付けちゃったよ……」といった凡ミスも避けられます。

 ここで書いたのはシンプルなクエリですが、他の言語環境、フレームワークでありがちなミスが起きづらい、プログラマにとって非常に快適な環境であることがお分かりいただけるでしょう。繰り返しになりますが、これはLINQが「言語に統合されたクエリである=クエリ自体がコンパイル可能である」ことによるメリットです。

 ここでは数値比較、文字列部分一致、リストに含まれるか、という条件を使いましたが、LINQが実際にどのようなSQLに変換されるかについては、第3回で詳細に解説します。


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

著者プロフィール

  • WINGSプロジェクト 土井 毅(ドイ ツヨシ)

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

  • 山田 祥寛(ヤマダ ヨシヒロ)

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XMLD...

バックナンバー

連載:Visual StudioでDB連携も簡単プログラミング ~知っておきたいLINQメソッド式&ラムダ式
All contents copyright © 2005-2018 Shoeisha Co., Ltd. All rights reserved. ver.1.5