WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

EF Core で SQL Server に渡される SQL 文の確認

by WebSurfer 2021年2月19日 16:27

開発時に Entity Framework から SQL Server に渡される SQL 文を確認したいことがあると思います。EF6 と違って EF Core ではそれは少々面倒だったのですが、EF Core 5.0 で導入された「シンプルなログ」という機能を使えば EF6 並みに簡単にできるようになったとのことなので試してみました。

EF Core の SQL 文

その「シンプルなログ」機能を使って EF Core が SQL Server に発行した SQL 文を Visual Studio の出力ウィンドウに表示したのが上の画像です。

基本的には DbContextOptionsBuilder.LogTo メソッドを使ってコンテキストクラスにアクセスして EF Core ログを取得し、指定の場所にログを書き出すという操作になるようです。

NuGet パッケージの追加、構成の変更、コードの大幅な書き換えなどは必要なく、Microsoft のドキュメント「シンプルなログ」に書かれているように、コンテキストクラスの OnConfiguring メソッドに一行追加するだけで EF Core ログの取得が可能になります。

具体的には、例えば先の記事「スキャフォールディング機能 (CORE)」でリバースエンジニアリングで作成したコンテキストクラスを例に取ると、以下のように自動生成された OnConfiguring メソッドの中で LogTo メソッドを使って EF Core ログを取得し、それを Debug.WriteLine メソッドで書き出すという一行を追加すれば OK です。

using Microsoft.EntityFrameworkCore;
using MvcCore5App.Models;

namespace MvcCore5App.DAL
{
    public partial class NorthwindContext : DbContext
    {
        public NorthwindContext(DbContextOptions<NorthwindContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Category> Categories { get; set; }
        public virtual DbSet<Product> Products { get; set; }
        public virtual DbSet<Supplier> Suppliers { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // 出力ウィンドウに EF Core ログを表示
            optionsBuilder.LogTo(msg => System.Diagnostics.Debug.WriteLine(msg));

            // ・・・中略・・・
        }

        // ・・・中略・・・
    }
}

上の LogTo メソッドにより、Visual Studio でデバッグ実行した際に EF Core ログが出力ウィンドウに表示され、その中に EF Core から SQL Server に渡される SQL 文が含まれるようになります。

例えば、以下のような Linq to Entities 文をコントローラーのアクションメソッドに書いて Visual Studio でデバッグ実行し、そのアクションメソッドをブラウザから呼び出してから出力ウィンドウを見ると、この記事の一番上の画像の SQL 文が発行されているのが確認できます。

namespace MvcCore5App.Controllers
{
    public class ProductsController : Controller
    {
        private readonly NorthwindContext _context;

        public ProductsController(NorthwindContext context)
        {
            _context = context;
        }

        public IActionResult Index()
        {
            // どのような SQL 文が投げられるかの検証用
            var list = _context.Products.OrderBy(p => p.ProductId).
                                         Skip(20).Take(10).ToList();

            // ・・・中略・・・
        }

        // ・・・中略・・・
    }
}

上に紹介した「シンプルなログ」は開発時限定でログを取ることを目的としているようで、運用時などでのログの取得には別の機能があるそうです。詳しくは Microsoft のドキュメント「ログとインターセプトの概要」を見てください。


最後に、EF6 で SQL Server に渡される SQL 文を確認する方法もついでに書いておきます。下の画像が EF6 のログを出力ウィンドウに書き出して、その中に含まれる SQL 文の部分を示したものです。

EF6 の SQL 文

基本的には EF Core と同様にコンテキストクラスからログを得て Visual Studio の出力ウィンドウに書き出すのですが、それには DbContext.Database.Log プロパティ を以下のように使います。

namespace Mvc5App.Controllers
{
    public class ProductsController : Controller
    {
        private NORTHWINDEntities db = new NORTHWINDEntities();

        public ActionResult Index()
        {
            // 出力ウィンドウに EF6 ログを表示
            db.Database.Log = msg => System.Diagnostics.Debug.Write(msg);

            var list = db.Products.OrderBy(p => p.ProductID).
                                   Skip(20).Take(10).ToList();

            // ・・・中略・・・
        }
    }
}

元々はログを取るための機能で、SQL 文を確認するだけでなく他にもいろいろ情報が取得できるようです。詳しくは Microsoft のドキュメント「データベース操作のログ記録と受信」を見てください。

Tags: , , ,

ADO.NET

[デバッグの停止] で止まらない

by WebSurfer 2010年8月31日 16:28

Visual Studio でデバッグ

Visual Studio で ASP.NET の Web アプリケーションをデバッグしている時の話です。

表題に「止まらない」と書きましたが、正確には、デバッガは止まるものの、コードはデバッガのコントロールが外れて実行されていき、メモリが開放されて終了するまで走っていってしまうということです。

従って、DB の更新などのコードがある場合、その手前でブレークポイントを設けて実行を止め、[デバッグの停止(E)]をしても DB の更新が行われてしまいます。デバッガのバグとかではなくて、そういう仕様だそうです。

ウソだと思う人は(笑)、以下に検証するためのコードをアップしておきますので、適当なところにブレークポイントを設けて試してみてください。ブレークポイントで [デバッグの停止] をしても、その後のコードは実行され、ファイル(file1.txt ~ file3.txt)はすべて作成されるはずです。

なお、このサンプルを動作させるには、アプリケーションルート直下に Files という既存のフォルダがあり、IIS のワーカープロセスがそのフォルダに対して必要なアクセス権を持っている必要がありますので注意してください。

<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
  protected void Page_Load(object sender, EventArgs e)
  {
    string path = Server.MapPath("~/Files/file1.txt");
    using (StreamWriter writer = File.CreateText(path))
    {
      writer.WriteLine("Hello World!");
    }

    path = Server.MapPath("~/Files/file2.txt");
    using (StreamWriter writer = File.CreateText(path))
    {
      writer.WriteLine("Welcome!");
    }
  }

  protected void Page_Unload(object sender, EventArgs e)
  {
    string path = Server.MapPath("~/Files/file3.txt");
    using (StreamWriter writer = File.CreateText(path))
    {
      writer.WriteLine("Goodbye!");
    }
  }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <h1>[デバッグの停止] で止まらない?</h1>
  </div>
  </form>
</body>
</html>

デバッグが止まっても実行が止まらないのは、Visual Studio のデフォルト設定(マネージド・コード用のデバッガを使用)における仕様だそうです。

設定によってデバッグの停止と共に実行を止めることは可能です。

Web サイトプロジェクトの場合、ソリューションエクスプローラのアプリケーションルートの右クリックで表示されるコンテキストメニューから[開始オプション(O)...]を開いて、[デバッガー]のオプションで[ネイティブコード(V)]にチェックを入れてみてください。

(注: Visual Studio Community 2015 の Web サイトプロジェクトの場合、[開始オプション(O)...]⇒[デバッガー]のオプションに[ネイティブコード(V)]がありません。別の設定方法があるかもしれませんが調べ切れてません)

Web アプリケーションプロジェクトの場合は、ソリューションエクスプローラの Properties を右クリックして開き[Web]タブを選択すると[デバッガー]の項目の中に[ネイティブ コード(C)]があります。

これにより、デバッガを起動するたびにネイティブコード用デバッガが読み込まれるそうです。結果、デバッグの停止と共に実行も止まります。

ただし、 [ネイティブコード(V)]にチェックを入れた設定でデバッグを停止すると強制的に Web サーバーを停止することになるそうです。それは好ましいことではないということで、デフォルトではデバッグを停止しても実行は止まらないようになっているようです。

なので、自分の場合、Web サーバーの強制停止による好ましからぬ副作用があるとイヤなので、そういうものだ(デバッグを停止しても実行は止まらない)と理解した上で、デフォルト設定のまま使っています。

Tags:

DevelopmentTools

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar