服務宗旨

網智數位主要提供套裝及客製化的軟體系統解決方案,專為客戶量身訂做客製化的軟體,達成客製化、智慧化及網路化的管理功能。

我們的成立宗旨就是要以最猛的IT技術讓這個世界更Smart,在我們貫徹我們裡想的同時,我們希望可以把我們所開發的系統帶給台灣的中小企業,除了要推薦好的東西之外,我們也希望做點改變,所以我們的第一目標就是要使用最好用的系統再加上您寶貴的創意,不僅僅可以節省你大量的荷包,還可以有一個像樣的網站。我們可以幫你做的有

企業管理
  • 策略管理
  • 目標管理
  • 行銷管理
  • 財會管理
  • ERP導入
  • 企業流程自訂
資訊管理
  • 網站架設
  • 虛擬化/雲端架設
  • 主機代管
  • 私有雲建制與導入
軟體開發
  • UML設計
  • 版本控管
  • 企業軟體開發
  • APP開發
  • 網頁設計
資訊安全
  • 網頁弱點掃描
  • 主機弱點掃描
  • 木馬檢測
  • 資安鑑識
  • 設計網路架構
  • 資安監控
行銷
  • 關鍵字SEO
  • 社群網路行銷
  • 部落格行銷
  • FaceBook 粉絲團
其他
  • 協助企業申請Google Email
好玩工具開發

講出你的創意吧!沒有甚麼是資訊辦不到的

2014年11月12日 星期三

[Entity Framework] 效能深入探討(二)

     在上一篇我花了一些時間談到,當我們載入資料庫模型是屬於 1 對多 (One-To-Many)時,預設值 Entity Framework 6 是利用一個稱為 Lazy Loading 機制,也就是當需要一個資料的其他相關(關聯)資料時,EF 才會產生SQL語法去跟後端資料庫要求相關資料,而資料應用程式效能的殺手之一,就是太繁複去跟後端資料庫來回存取,為了克服 EF 預設行為的效能問題,我想來介紹一個 EF 另外一個機制術語,稱為 Eager Loading ....


 

     使用 Eager Loading 機制,主要可以在一開始讀取資料時,例如讀取 Customer Table 時,如果我們知道後續一定會讀取相關聯的資料表(類別),如案例的 CustomerCate Table、CustomerEvent Table,那麼我們就可以在第一次讀取 Customer Table 時就一次讀取所有相關的資料表,這樣後續應用程式需要相關資料時,只要在記憶體立即讀取,而不是需要用到時,才延遲跟資料庫索取相關資料,解釋那麼多,到底程式語法該如何實作呢?我們會用到一個方法(Method)為 Include ....

    PS.這次實作我完全根據 上一篇[Entity Framework] 效能深入探討(一) 繼續介紹,前端我暫時利用 Windows Form 來簡單的 Demo
,然後我會把焦點放在 Include Loading(1) 與  Include Loading(2) 的 程式語法
 

在  Include Loading(1) Button Click事件,我撰寫了一些程式碼:

  1. this.richTextBox1.Clear();
  2. this.richTextBox1.AppendText("使用 Eager Loading 機制 Include Method ! \r\n");
  3. this.richTextBox1.AppendText("------------------------------------------------------------------------- \r\n");

  4. using (CRMEF ef = new CRMEF())
  5. {
  6.      var customers = ef.Customer.Include("CustomerCate").Include("CustomerEvent");

  7.      foreach (var cust in customers)
  8.      {
  9.           this.richTextBox1.AppendText("客戶編號 : " + cust.No + " 客戶姓名 :" + cust.ENmae + "\t  類型 :" + cust.CustomerCate.Name + "\r\n");
  10.           this.richTextBox1.AppendText("--------------------------------事件記錄------------------------------------ \r\n");

  11.           foreach (var evt in cust.CustomerEvent)
  12.           {
  13.                this.richTextBox1.AppendText(evt.Desc + "\r\n");
  14.           }

  15.           this.richTextBox1.AppendText("\r\r\n");
  16.      }
  17. }

     注意上述程式碼的第 7 行我使用了2次 Include 方法,並在該方法傳遞是關聯類型的字串,透過這樣的方式,但程式第一次需要讀取 Customer 資料表時,
Entity Framewok(EF)就會自動產生的 SQL語法是把 Customer、CustomerCate、CustomerEvent 3個 Table,一次完全跟後端資料庫的索取,並記錄到記憶體(DataContext Cache),所以整個 SQL 傳輸只有 1 次,而不是上一篇介紹的 7 次哦(效能差很大,這也是一般書上很少寫的)。

底下我列出我追蹤的 SQL 語法如下
  1. SELECT
  2.     [Project1] .[C1] AS [C1],
  3.     [Project1] .[No] AS [No],
  4.     [Project1] .[CName] AS [CName],
  5.     [Project1] .[ENmae] AS [ENmae],
  6.     [Project1] .[CateCode] AS [CateCode],
  7.     [Project1] .[Code] AS [Code],
  8.     [Project1] .[Name] AS [Name],
  9.     [Project1] .[C2] AS [C2],
  10.     [Project1] .[EventID] AS [EventID],
  11.     [Project1] .[CustNo] AS [CustNo],
  12.     [Project1] .[Desc] AS [Desc],
  13.     [Project1] .[CreateDate] AS [CreateDate]
  14.      FROM ( SELECT
  15.         [Extent1] .[No] AS [No],
  16.         [Extent1] .[CName] AS [CName],
  17.         [Extent1] .[ENmae] AS [ENmae],
  18.         [Extent1] .[CateCode] AS [CateCode],
  19.         [Extent2] .[Code] AS [Code],
  20.         [Extent2] .[Name] AS [Name],
  21.         1 AS [C1],
  22.         [Extent3] .[EventID] AS [EventID],
  23.         [Extent3] .[CustNo] AS [CustNo],
  24.         [Extent3] .[Desc] AS [Desc],
  25.         [Extent3] .[CreateDate] AS [CreateDate],
  26.          CASE WHEN ([Extent3]. [EventID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
  27.          FROM   [dbo]. [Customer] AS [Extent1]
  28.          LEFT OUTER JOIN [dbo] .[CustomerCate] AS [Extent2] ON [Extent1] .[CateCode] = [Extent2].[Code]
  29.          LEFT OUTER JOIN [dbo] .[CustomerEvent] AS [Extent3] ON [Extent1] .[No] = [Extent3].[CustNo]
  30.      )  AS [Project1]
  31.      ORDER BY [Project1].[No] ASC, [Project1] .[Code] ASC , [Project1]. [C2] ASC


看吧看吧,是不是 EF很聰明的產生一個完全都包含的表格(Table)。


接下來,我們來看第二種 Include 語法的寫法,2種執行結果都相同。

  1. this.richTextBox1.Clear();
  2. this.richTextBox1.AppendText("使用 Eager Loading 機制 Include Method 2 ! \r\n");
  3. this.richTextBox1.AppendText("------------------------------------------------------------------------- \r\n");

  4. using (CRMEF ef = new CRMEF())
  5. {
  6.      var customers = ef.Customer.Include(t => t.CustomerCate).Include(t => t.CustomerEvent);

  7.      foreach (var cust in customers)
  8.      {
  9.           this.richTextBox1.AppendText("客戶編號 : " + cust.No + " 客戶姓名 :" + cust.ENmae + "\t  類型 :" + cust.CustomerCate.Name + "\r\n");
  10.           this.richTextBox1.AppendText("--------------------------------事件記錄------------------------------------ \r\n");

  11.           foreach (var evt in cust.CustomerEvent)
  12.           {
  13.                this.richTextBox1.AppendText(evt.Desc + "\r\n");
  14.           }

  15.           this.richTextBox1.AppendText("\r\r\n");
  16.      }
  17. }

以上介紹完 Eager Loading Inclue 的技巧,希望各位操控 EntityFramework 6 可以更加熟析在最適當的狀況下,來調整預設存取行為機制。



1 則留言:

如您對本文有任何建議或意見,歡迎您留下您寶貴的意見!