Pages

2015-05-09

導入EF之初期策略

是否你仍在使用ADO.NET+DataTable方式存取資料庫,心裏卻很想導入EF (Entity Framework v6.x)架構,但在看了不少LINQ及EF的範例碼後,覺得語法雖簡鍊,但對其細節掌握度不好呢?其實你的直覺是對的,Entity有它的好處,但要完全取代SQL,現階段是做不到的。

以下圖為例,你若走一般書上教的編號1路線,若你對C# Lambda及LINQ相關物件集合不是很了解的話,很容易陷入效能危機。新手程式員為了求結果,一直用Fluent Syntax一直串接集合,當資料量一大,效能就變極差。如同一位好的程式員在讀取UI樹狀結構資料時,他懂得怎麼下簡單的SQL取回最少資料量,再於Client端用程式作結構上的映射,而不是直接在DB裏下一大串子查詢及遞迴SQL的過程。

EF to Entity

LINQ在SQL Expression的自動轉換上,無法作到像傳統SQL那麼精確,例如你要把某日期欄位在更新資料時寫入DB主機時間,EF是沒辦法直接用GETDATE()的,就算真要做到這功能,也是至DB端取得時間變數再查詢寫入的,雖然能達到目的,但這種耗損效能的行為不可取。很多人接觸EF之初,就以為可以不用再寫SQL指令,其實EF的精神在於Entity資料集合上,而非100%要用LINQ取代SQL。

至目前EF v6.x版,DataTable是可以完全被取代掉的,使用IEnumerable<T>來代替,這在程式撰寫上會得到很多好處。但LINQ to SQL這部分的語法轉換無法完全取代,所以還是得用DbContext.Database.ExecuteSqlCommand()來執行傳統SQL字串。這部分和傳統ADO.NET+DbParameter使用方式一樣,其實這部分可以直接使用自己寫的DbHelper來讀入EF下的DbConnection來實現。主要原因是EF目前執行SQL指令的函式,其傳回的Entity類別必須與Select欄位數完全一致,也無法直接傳回dynamic集合,在使用上的語法不夠直覺、簡單。

SQL Profiler

我的導入方式是,在完全理解LINQ及Lambda函式設計之後,確認它在底層的實作沒包藏太多耗損效能垃圾,然後去了解IEnumerable<T>集合,以Entity的理念重新改寫我的DbHelper物件。內容包括實作資料庫ORM讀取及匿名類別、映射Reflection、動態dynamic等新的方式,讓我的DbHelper可以用Entity的概念去讀取接收資料,並產生與EF同結果的集合資料。當用新思維走過一圈後再回頭看EF的架構,更能透視它函式實作原理,達到去繁入簡的學習。

如上圖編號3,當遇到LINQ無法完全轉成我預期的SQL指令時,我就會切入自己的DbHelper產生預期的資料結果。我不是迴避LINQ,只是因為更了解它的限制及效能缺點(SQL Profiler一直開著),使用更直覺、更高效能的方式去解決問題而己。

No comments: