SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

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

N+1問題を回避せよ! LINQから出力されるSQLを見てみよう&遅延ローディングの光と闇

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

  • X ポスト
  • このエントリーをはてなブックマークに追加

 本連載では、データベースプログラミングにおいてLINQをどのように活用できるのか、解説していきます。今回は、LINQが実際にはどんなSQLに変換されているのかを確認し、遅延ローディングの有無による処理の変化について解説します。

  • X ポスト
  • このエントリーをはてなブックマークに追加

前回のおさらい

 前回の記事では、データベースに対してLINQメソッド式を使ってクエリを実行する方法について解説しました。多数の条件が指定された場合でも、メソッドチェーン式にメソッドを積み重ねることで簡単に実装できることを確認できました。

 今回は、LINQが実際にはどんなSQLに変換されているのかを確認します。また、遅延ローディングの有無によってどのように処理が変わるかを意識し、パフォーマンス問題を解決する方法について解説します。なお、前回作成したサンプルを今回も引き続き使用します。

出力されるSQLを確認してみよう

 前回の解説通り、Entity Frameworkは、LINQのクエリ式やメソッド式を、最終的にSQLへと変換してデータベース上で実行しています。この変換は透過的に行われるため、プログラマはLINQを記述する際にSQLをそれほど意識する必要がありません。しかし、データベースプログラミングを行っている以上、実際にどんなSQLが実行されているかを理解するのは重要です。自分が書いたLINQがどのようなSQLとして実行されるかが理解できていないと、後ほど解説するようなパフォーマンス上の問題にぶつかることになります。データベースプログラミングにおいては「ただクエリ結果が正しければいい」だけでなく「データベースに不要な負荷を掛けないようにクエリを投げる」のも重要です。

 Entity Frameworkから実際に出力されるSQLを確認するには、リスト1の①のように、コンテキストクラスのDatabaseプロパティで取得できるSystem.Data.Entity.DatabaseオブジェクトのLogプロパティに、ログを出力するためのメソッドを指定します。なお、この機能はEntity Framework 6から追加されたものです。これだけで、Entity FrameworkからSQLを実行する際、SQLの内容やパラメータ、実行時間などが指定したメソッドの引数として渡されます。

リスト1 ログ出力の方法
using (var context = new CodeZineSampleContext())
{
  //①コンテキストクラスのDatabase.Logプロパティを使って
  //実際に発行されるSQLをコンソールに出力する
  context.Database.Log = Console.WriteLine;
  //②全件出力してみる
  IQueryable<Product> products = context.Products;
  //③結果をループして出力する
  foreach (var product in products)
  {
    //商品名だけ出力
    Console.WriteLine(product.Name);
  }
}

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

リスト2 Entity Frameworkが実際に発行しているSQL
2014/10/26 0:33:35 +09:00
 で接続を開きました
SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[Name] AS [Name],
    [Extent1].[Price] AS [Price],
    [Extent1].[Employee_Id] AS [Employee_Id],
    [Extent1].[Maker_Id] AS [Maker_Id]
    FROM [dbo].[Products] AS [Extent1]
-- 2014/10/26 0:33:35 +09:00
 で実行しています
-- 6 ミリ秒で完了しました。結果: SqlDataReader
注釈

 実際には、上記のSQLProductsテーブルへアクセスする前に、[INFORMATION_SCHEMA.TABLES]や[__MigrationHistory]テーブルにアクセスするSQLが発行されます。これはEntity Frameworkがソースコードのエンティティとデータベースのテーブル定義の同期を取るために、データベース初回アクセス時に自動的に発行されるもので、LINQとは無関係です。

 SQLの内容としては、ProductsテーブルのすべてのフィールドをSELECTするだけのシンプルなものです。特に条件を指定しない全件出力ですので、想定通りのSQLと言っていいでしょう。

 さて、ログが出力されたタイミングにも注目しましょう。ブレークポイントを②の箇所に仕掛けてデバッグ実行し、一行ずつステップ実行してみてください。②の全件出力の時点ではSQLは発行されず、③のforeach文を実行するタイミングでログが出力されることが確認できるでしょう。前回も解説しましたが、Entity Frameworkは、実際にデータを使うタイミングになって初めてSQLの発行を行います。

Whereメソッドで条件を指定した場合のSQL

 続いて、LINQのWhereメソッドを使って条件を指定した場合のSQLも確認してみましょう(リスト3)。

リスト3 Whereメソッドで絞り込み
//Priceが300を超えるものだけ出力する
IQueryable<Product> products = context.Products.Where(x => x.Price > 300);
↓
SELECT
    [Extent1].[Id] AS [Id],
    [Extent1].[Name] AS [Name],
    [Extent1].[Price] AS [Price],
    [Extent1].[Employee_Id] AS [Employee_Id],
    [Extent1].[Maker_Id] AS [Maker_Id]
    FROM [dbo].[Products] AS [Extent1]
    WHERE [Extent1].[Price] > 300

 「x => x.Price > 300」というラムダ式は「WHERE [Extent1].[Price] > 300」というSQLに変換されています。こちらも概ね想定通りですね。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ
遅延ローディングとN+1問題

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Visual StudioでDB連携も簡単プログラミング ~知っておきたいLINQメソッド式&ラムダ式連載記事一覧

もっと読む

この記事の著者

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

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

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

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

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/8415 2015/02/03 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング