LINQ to SQL の場合は Log プロパティを使う
LINQ to SQLのログ出力をVisual Studioの[出力]ウィンドウに出力するには?[3.5、C#、VB] - @IT
http://www.atmarkit.co.jp/fdotnet/dotnettips/801linqoutput/linqoutput.html
ってことで良いのですが、LINQ to Entities の場合は、ObjectQuery クラスにキャストして ToTraceString を使うってのが常套手段らしいです。
[C#]LINQ to Entitiesで発行されているSQL文を見たい
http://blogs.wankuma.com/kazuki/archive/2009/06/01/173926.aspx
上で示されているようなメソッドを作ればよいので、ASP.NET MVC で CakePHP 風な実行クエリを表示するようにしてみます。クエリを表示させると SQL Server Management Studio などで実行できるので確認が楽なんですよね。後、変なクエリをしていないかを確認できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | using System.Data.Objects; public static class DebugSQL { private static string _sql; public static string SQL { get { return _sql; } } public static void ToTraceString<T>(IQueryable<T> query) { var objectQuery = query as ObjectQuery; if (objectQuery != null ) { _sql = objectQuery.ToTraceString(); } else { _sql = "no sql;" ; } } } |
こんな形で、static class を定義しておきます。これだと1回のクエリしか保存できないので、複数回のクエリも保存したいですね。これは後程修正します。
そしてコントローラー中で、
1 2 3 4 | var items = from t in ent.wp_terms where t.wp_term_taxonomy.FirstOrDefault().taxonomy == "category" select t; DebugSQL.ToTraceString(items); |
のように LINQ を実行した後に、DebugSQL.ToTraceString で SQL を保存しておきます。
これを画面に表示する時には、CakePHP のようにマスターページを使いたいので、Site.Master を変更します。
1 2 3 4 5 6 7 8 9 | < div id = "main" > < asp:ContentPlaceHolder ID = "MainContent" runat = "server" /> < div id = "debug" > < h2 >実行クエリ</ h2 > <%: ViewData["SQL"] %> </ div > < div id = "footer" > </ div > </ div > |
こんな風に ViewData を使えばいいです。
これを設定するために、コントローラーで ViewData を指定します。
1 2 3 4 5 6 7 | public ActionResult Index() { Models.CategoryModel cate = new Models.CategoryModel(); var model = cate.GetCategories(); ViewData[ "SQL" ] = Models.DebugSQL.SQL; return View(model); } |
CakePHP ではレイアウトのページで実行SQLを表示しているので、この手のデバッグ情報はコントローラーやモデルには書きたくないところですよね。。。ちょっと工夫したいところです。
まぁ、それでも一応、実行するとうまくクエリが取れます。
このクエリを SQL Serve Management Studio で実行するとこんな感じ。
実は、Visual Studio 2010 上でもクエリが実行できて、サーバーエクスプローラーから「新しいクエリ」でペインを開けます。
余分なウィンドウを消して、クエリを実行すると(余計なことに)クエリ文を整形してくれます。
元のクエリ文が残らないのでちょっと不安なのですが、うまくサブクエリになっている(笑)ことがわかります。
出力された結果が微妙なサブクエリになっているところが不安を醸し出します。アソシエーション経由でクエリを掛けるとこんな感じになるんですねぇ。わざわざ TOP を使ってサブクエリになっているのは FirstOrDefault メソッドを使っているからなので、このあたりは EDM の アソシエーションを 1対1 にすれば直るのかもしれません。