2012年1月6日 星期五

觀察 Entity Framework 轉換所產出的 SQL Command

在前一篇文章「LINQPad + Oracle ODAC for Entity Framework」介紹了可以藉由LINQPad載入專案組件後就可以在LINQPad中操作LINQ Query,以達到程式實作前的測試操作,如果專案所使用的資料庫是 MS SQL Server 的話,在LINQPad中可以直接觀察EF所產出的 SQL Command,但要是專案所使用的資料庫是 Oracle,那麼在LINQPad就無法看到EF所產出的SQL Command,這種情況下就必須要回到Visual Studio中於偵錯模式下進行EF產出SQL Command 的觀察了,所以在本篇文章中將會說明幾種在Visual Studio的偵錯模式下觀察由Entity Framework所產出的SQL Command。

註:本篇將會著重於 Oracle ODAC for Entity Framework 情境下的解決方式,而有關使用 MS SQL Server 的專案,可以參考以下文章:

Jerry - 我的Coding :查看LINQ Expression編譯後的SQL語法

 



方法一:使用 ObjectQuery's ToTraceString Property

這方式的操作方式相當簡單,有兩種方式來使用這個方法,但都必須在偵錯模式下才能運作,其實這個方法的使用相當簡單,

例如,我們有以下的一個LINQ Query Expression

var query = from o in db.Orders
            OrderBy o.OrderID
            select o;

而在偵錯模式下去使用以下的程式,就可以輸出EF所產出的SQL Command

((System.Data.Objects.ObjectQuery)query).ToTraceString();

以下就來看看兩種實際應用的例子。

 

第一種方式:

在要執行偵錯的Method中去下中斷點,

image

進入偵錯模式,當程式執行到第27行之後,在「即時運算視窗」中去輸入「((System.Data.Objects.ObjectQuery)query).ToTraceString();」

image

輸入完後就按下「Enter」,就可以在「即時運算視窗」輸出由 EF所轉換的SQL Command,

image

 

第二種方式:

如果說,上面的那一種方式所得到的SQL Command不容易清楚的閱讀,我們也可以在Method中直接去執行輸出的程式,

image

接著進入偵錯模式,執行到第29行過後,將滑鼠游標移到「traceString」上面就可以看到輸出的SQL Command,

image

或是滑鼠游標移到「traceString」上面時,去點選IntelliSence所顯示的「放大鏡圖示」

image

文字視覺化顯示

SNAGHTMLb90090

複製產出的SQL Command並且貼到可以執行SQL Command的環境下執行,下圖的執行環境是「Navicat」

image

 

 

方法二:使用Entity Visualizer

有關這個Visual Studio套件的下載與使用,可以參考保哥的文章「介紹好用 Visual Studio 2010 擴充套件:Entity Visualizer」,文章中有詳細的說明,特別提醒一下,Entity Visualizer只能在 使用 .NET  Framework 4.0 的專案中使用,所以只限定VS2010,如果是64-bit的環境,在保哥文章的評論區最後有提供 64-bit 的版本下載。

實際操作:

我們把剛才方法一在Method中所加入的程式給移除,並重新設定中斷點,

image

進入偵錯模式,當程式執行到第29行的時候,滑鼠游標移到 query 的變數上,出現IntelliSence後點擊「放大鏡」圖示,

image

General SQL

SNAGHTMLc90a6f

 

 

方法三:執行SQL指令

有些人是不喜歡在偵錯時才能去觀察EF產出的SQL Command,那如果系統已經上線或是非偵測模式下,那不就不能觀察產出的SQL嗎?

而使用LINQPad做LINQ Query Expression的操作測試,就無法即時產出Oracle的SQL Command……

因為Oracle並沒有MS SQL Server那樣有提供SQL Profiler的工具(MS SQL Server完整版才有, Express版沒有),雖然有相關的工具可以Profiler Oralce的SQL Command,但好用的要錢,不用錢的也不是很好用。

在LINQPad中去執行LINQ Query Expression:

image

接著在Navicat的Query中去執行以下的SQL Command:

select module,first_load_time ,sql_text
from v$sql
where
    TO_DATE(first_load_time,'yyyy-mm-dd hh24:mi:ss') <= SYSDATE
order by first_load_time desc;

執行結果:

可以於查詢結果中看到第一筆資料,「MODULE」欄位是「LINQPad.exe」而其執行的SQL Command就記錄在「SQL_TEXT」欄位中

image

 

如果是在Visual Studio的偵測模式下執行,在Profiler的查詢結果如下:

image

是不是會覺得很雜亂呢?因為沒有去過濾「MODULE」欄位的值,執行 Profiler 的 SQL Command 時就會把所有的執行Profiler給撈出來,所以我們可以對 Profiler SQL Command去增加過濾MODULE的條件值,因為我的專案是使用 IISExpress 為程式開發伺服器,所以Profiler SQL Command就改成以下的內容:

select module,first_load_time ,sql_text
from v$sql
where
    TO_DATE(first_load_time,'yyyy-mm-dd hh24:mi:ss') <= SYSDATE
    and MODULE = 'iisexpress.exe'
order by first_load_time desc;

於Navicat中執行的查詢結果:

image

如果說,你的程式開發 Web 伺服器是使用 Visual Studio 所預設的,或是開發專案的網站已經附加到IIS伺服器的網站,我必須說…有時還真的找不到 MODULE 為「WebServer.exe」與 MODULE 為「w3wp.exe」的資料……

不過這個Profile SQL Command 倒是跟 LINQPad 蠻合得來,因為都可以正確無誤的把LINQPad 查詢給記錄起來,所以我會建議要在LINQPad中去觀察EF所產出的Oracle SQL Command,可以配合這個方法:

select module,first_load_time ,sql_text
from v$sql
where
    TO_DATE(first_load_time,'yyyy-mm-dd hh24:mi:ss') <= SYSDATE
    and MODULE = 'LINQPad.exe'
order by first_load_time desc;

 

其他方式:

MS SQL Server

如果專案使傭MS SQL Server而開發環境只有安裝MS SQL Server Express Management Studio,想要有SQL Profiler的功能,建議可以使用「AnjLab Sql Profiler」,這是一套免費的工具軟體,同樣提供與MS SQL Server SQL Profiler一樣的功能。

 

Oracle

如前面所說的,Oracle 資料庫如同比較少像 MS SQL Server SQL Profiler 同樣功能的監測工具,而有提同樣功能的工具也所費不貲,不過 Will 保哥有在他的文章裡分享一個工具:「Statement Tracer for Oracle」「Will - 保哥 : 介紹好用工具:Statement Tracer for Oracle」,經由 Google 查詢有關 Oracle 的 SQL Profiler 結果,查詢結果有一堆會說有哪些工具有提供相同的功能,但有的工具要錢不然就是是不出來。

 


藉由此篇來說明專案如果使用Oracle ODAC for Entity Framework 的情況下,如何取得由EF所產出的SQL Command,而使用MS SQL Server的專案就有最直接的支援工具可以善加利用。

 

延伸閱讀:

Visual Studio Magazine - Seeing the SQL Generated by LINQ to Entity Queries

http://visualstudiomagazine.com/blogs/tool-tracker/2011/11/seeing-the-sql.aspx

 

MKing's Blog - Oracle PL/SQL Profiler应用指南

http://blog.csdn.net/yzsind/article/details/351267

 

以上

4 則留言:

  1. 讚,好用!!!,謝啦

    回覆刪除
  2. 水!!
    請問有什麼機制可以run time時期存放執行了哪些update/insert的指令?

    回覆刪除
    回覆
    1. Hello, 可以參考 Jarek Kowalski 所寫的「Tracing and Caching for Entity Framework available on MSDN Code Gallery (http://goo.gl/4gzp8)」以及「Logging SQL statements in Entity Framework/Code First (http://goo.gl/WXIuO)」.

      刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。