網頁

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)」.

      刪除