開發 WP 搭配 Entity Framework 的 除錯歷程
Entity Framework 從第一代用到現在也有一陣子了,做為 .NET Framework 的 ORM 的確是一個還蠻方便的套件,尤其是 DAL 層的 Code 可以少寫非常多。 ( 沒辦法~~懶嘛 ) 即然可以有更少的 code 可以達到一樣的功能為什麼不用呢?當然從另一個角度來看也是同時希望在實務上了解差異和優勢。
說真的 EF 有些時候除錯上真的沒那麼直覺,由其是 ORM 必須要很明確地將 DB Schema 和 Object Mapping 而且像我自已的習慣一定會有 FK 機制,所以對於關聯性的要求就更高。
雖然現在 EF 5 , 6 的錯誤訊息說真的已經明確非常多了,像我是開發 Windows Phone APP + Azure Cloud Service 的方式除錯的話。往往就是會遇到一堆羅生門的事。
只有加新功能的 WS,舊功能就死了
好吧!!我承認是自已沒有跑 Unit Test 的錯,明明有寫了卻沒有 Run UT 就是自已活該浪費時間 。 (倒)
即有的 WS 的 Interface 和 業務邏輯都沒有變更,只有加上新功能的 WS 和 業務邏輯。當然 DB 只有加上新功能所需要的 Table ,即有的 Table 都沒有動到。基本上這件事在 ADO.NET 是絕對沒有問題的,但 WP APP 一連線到 Server 上新增店家資料就立刻發生錯誤。
在手機上怎麼會有詳細的 Exception 資訊呢!只有很簡單的「新增店家資料失敗」的訊息。
當下有兩個想法
一、是不是我的店家資料送的參數有錯?新的 Bug 當初沒有找到?
二、還是 EF 出錯 <-- 通常認為不可能的就是這裡死掉
回到家後立馬下載了 IntelliTrace 的資料回來看 可以參考 [Memo]如何分析 Azure SDK 的除錯資訊 - IntelliTrace
出現了一堆看不懂的錯誤訊息,不過從中挑了 Schema 規格不符合驗證的錯誤來看
這個時候出現了 EF 所有的 Code Map 執行歷程,這裡是出現 EF 驗證欄位出錯。但我還是想確認一下是不是我自已的 Code 所造成的
首先先看 AddStoreDto 傳入的參數是否都正確
經這個步驟立刻就排除 WP APP 傳入的參數是正確無誤的
OK,那從 Code Map 的圖形再繼續往下看知道是 FK 設定的關係,因為光是在載入 DTO 物件就不符合 EF 的對應
Schema specified is not valid. Errors:
The relationship 'EasyDrinkDBModel.FK_Store_Brand' was not loaded because the type 'EasyDrinkDBModel.Brand' is not available.
The following information may be useful in resolving the previous error:
The required property 'Product' does not exist on the type 'EasyDrinkDLL.Dto.Brand'.
回到 EF 的 Edmx 圖形來看,舊的功能是只有用到 Store / Brand 這兩個 Table 。但因為我增加了 Product 和 Brand 之間的關聯,所以導致 Brand 的導覽屬性多增加了 Product 。
這個時候立刻就發現,當初偷懶沒有補上導覽屬性就是個錯。因為光是載入就失敗了
Bug 通常不只一個,還是接二連三
是的,上天給你的考驗通常不會只給你一個,是接二連三 ( 明明就是自已 code 沒寫好 )
反覆看到 EF 的流程之後會覺得每次都載入一堆物件都會好好考慮每一次的呼叫
The type 'Edm.Double' of the member 'AvgRanking' in the conceptual side type 'EasyDrinkDBModel.Product' does not match with the type 'System.Single' of the member 'AvgRanking' on the object side type 'EasyDrinkDLL.Dto.Product'.
這個錯誤我只能說自已太不用功了,因為 DB Schema 中 AvgRanking 我是定義 float ,所以呢 DTO 的型別自然地也寫成 float 。這樣子沒錯對吧 ( 飛踢)
最後去翻了 SQL Server 的型別定義後才注意到 DB 的 float 是 對應到 double
常常認為自已傳正確的值,但就是那個地方錯!
是的,我明明都有傳正確的參數啊, String 出來的預設值應該是 “”吧!怎麼會出錯呢?一定是後端的 Service 寫錯了對不對!
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
當然 UT 都是丟正確的值,所以一定是正確無誤的。
還是請出 IntelliTrace 出來,不到 10 秒我就默默地回去改 APP 的 Code 並加上正確的防呆機制
一切都正常了
雖然說用 Log 一樣可以暴力查出來,但以自已過往的經驗來看那實在是太累了,而已對於一些底層的機制可能沒有辦法那麼容易了解為什麼會這樣子。所以我自從在 2010 年西雅圖總部 看到 IntelliTrace CodeMap 的 雛形時非常的興奮,因為這完全改變了開發人員的除錯經驗和效益呢。
當然現在這已經是我在 Debug 上必備的工具之一,因為這無疑地減少我很多通靈的時間。 尤其是好幾個月才改這麼一次的時候