利用 POCO 解決 Entity Framework 的預設值 (Default Value) 寫入問題 v4

利用 POCO 解決 Entity Framework 的預設值 (Default Value) 寫入問題

經過 6 小時的實作和驗證後,原本文章 po 出來的作法,只有在小弟特定的專案和 UT  才可以執行   ( 原因尚不明 )

小弟重新建置相同的程式碼和資料庫後卻無法重現同樣的效果。

 

另外,雖然 很多文章在反應是 CSDL 有更新,但 SSDL 沒有更新是 Bug 。

但小弟導入 StoreGeneratedPattern = Computed 後,發現若是 SSDL 也改成 Computed 的話!

EF 就會忽略該欄位寫入的值,所以 之後要 update 其值就也不行。 

 

這對某些欄位是沒辦法接受的,因此 SSDL 沒有改的話!還比較沒問題。

至少可以在 DTO 物件中加上初始化值   或是 Insert 語法時避開 來解決。

 

若是手動改 SSDL 的話,只要重新拉 Model 或是 更新,則 SSDL 就會被更新成 None 。

 

ps.. 目前確定 Identity 和 TimeStamp 這兩個欄位型態會將 SSDL 的設成 Computed

 

所以,目前 EF 的 預設值 有2種做法

 

  1. AP 都不會讀取 和 寫入,就不要加入到 EF 的 Model 上,就可以解決 insert 問題 ( 就是不要出現在 CSDL 中)
  2. AP 會讀寫,請直接在 POCO 上直接加上 預設值。 ( 可以的話用 Nullable<T> 或是 型別? )

 

 

直到 L 問起時才發現原來有這樣子的問題

( 感謝 R 協助 )

 

問題是若資料庫有「預設值」的情況時, EF  就沒有辦法寫入

 

當時 L 找到的解法只就以下兩種,不管是那一種都很不方便

一、改寫 SSDL ( EDMX 檔 )   ( 這個只要做一次資料庫同步後,剛剛改的就會不見了 )

二、該欄位每次都填值進去  ( 程式塞值進去就不叫做 預設值了 )

 

這個問題在各討論版都有出現過了workaround 的方式

 

其實,有另外的做法可以解決這個問題!!!

 

 

一開始小弟都沒有注意到大概是因為,小弟在第一時間就已經改寫成 POCO 型式的關係

之前有 po 過 EF 4 改寫 POCO自動產生 POCO 物件 的文章,有興趣的可以參考

 

----------  請特別注意!  ----------------

v2

自訂工具「一定」要是空的喔!不然 Entity Framework 不會和 POCO 整合

不然等會更新 EDMX 的時候還是沒效果!!

image 

-------------------------------------------------

 

為了證明是真的 ( 有圖有真相 )

所以我們就從建置 DB 開始吧!!

 

image 
當然改 DB 要從 DB Project 開始,所有的修改都要納入版本管控,通常預設值都是不可為 null 的。
而且為了驗證多種不同的預設值,這裡特地加上了 TimeStamp 和 DateTime

 

image
建立預設條件!

 

image

image 
因為,TimeStamp 型別本身已經會產生值了,所以在這裡只要補上 CreateDate 的就好! 

 

都改好後就同步一份到 測試資料庫吧!!

 

Tip:若是您想要讓資料可以依 新增、修改 都會有最新的時間記錄的話。建議直接使用 TimeStamp就可以了,不需要另外再用程式去維護其最新的值。可以省下非常非常多的工

 

image
直接開始 EDMX 並同步一份最新的到模型上

image  

 image
確認一下 CreateDate 的屬性,的確 StoreGeneratedPattern 是 Computed ! ( 先聲明,我沒有去改 SSDL )

那~~ 另外一個欄位 TimeStamp 去那了? 因為 TimeStamp 我的程式都不會去動到,所以剛剛我先刪除了。

 

 

---------------------------------------------------

v3

現在我重新建置卻一直都是 None 可能是因為當時不小心點到了吧!很囧

不過,重新再進行驗證後,其實發現 StoreGeneratedPattern 有沒有設定都沒關係!

( 之前都有先入為主的觀念 Orz )

目前知道會自動產生StoreGeneratedPattern 只有 Identity 和 TimeStamp 兩種格式

 

v2

若是原來就已經有這個欄位的話!那麼 StoreGeneratedPattern 就會用原來舊的

請重新建立 或是 手動改成正確的就行了!

---------------------------------------------------

 

image 
因為模型上已經有了,所以 DTO 物件也要加上該對應欄位。不然會無法正常執行 
 

( 到目前為止只要加上這一行 code 就好,其他的都先不用動。 )

 

改好後就要驗證,剛剛新增的欄位是否會對「即有」程式造成影響

當然用單元測試來跑,馬上就可以確認了。 (  快速又簡單 )

 

image 
因為是預設值驗證,所以就直接拿原本的 UnitTest 連改都不需要
可以看到測試中只有用到 .Name 的屬性 (欄位) 

 

image 
太棒了!很快地~~ 測試通過了。

 

 image
因為這段程式會自動產生三個預設值,所以也一併確認資料庫的內容,都可以看到 TimeStamp 和 CreateDate 都有預設值。

v3:為了有圖有真像,還是稍微把過程中斷將圖抓出來。

 

 

所以證明當 Entity Framework 4 + POCO 的組合時,預設值的問題是完全不會受到影響的。

而且再也不需要擔心同步資料庫後,修改 SSDL 後會被改回去。