[C#.NET][Entity Framework] 使用 MetadataType 改變 EF 預設檢查行為 - Code first from database
資料庫的定義如下:
Name 是必填欄位,且有預設值空字串
小章廢言:
資料庫是儲存狀態的一個地方,保持狀態的可靠性,對系統而言是很重要的一件事,一但髒資料進到資料庫裡面,未來得花更大的力氣處理,債早晚都是要還的,別因小失大;資料庫要保存什麼狀態則是由功能需求決定,由功能需求的角度來看,便可決定欄位是否為必填,個人認為,應有兩種必填類型,一種是系統必填,另一種是使用者必填。
系統必填:經某種演算後填入或是初始化狀態
使用者必填:經由使用者在表單上填寫不論是什麼必填類型,給予空字串,彷彿是在告訴大家說『這個欄位很重要,但裡面沒有東西』;神偷開了一個國王戒備森嚴的保險箱,但裡面卻空空如也。
語意不清楚會造成日後維護的困擾,應用程式本身應有自己的資料檢查機制,不應該廢了資料庫的檢查機制
開始進入主題:
這裡我用的是Code first form database,詳細作法請參考 http://www.dotblogs.com.tw/yc421206/archive/2014/03/18/144430.aspx
EF 工具幫我產生了 Account 類別,對應到資料庫的 Account Table,Name 屬性則是對應到資料庫的 Name 欄位;Name 屬性有兩個 Attribute,它們是用來檢查資料格式用的:
Required:必填
StringLength(50):字串長度 50
public partial class Account { private string _name; public int Id { get; set; } [Required] [StringLength(50)] public string Name { get; set; } }
有了 Entity Framework 不需要花費精神檢查資料,若預設的檢查方式不如你所預期,要擴充也是相當簡單,本篇不會描述如何擴充
測試程式碼如下:
public class UnitTest1 { [TestMethod] public void TestMethod1() { DemoDbContext db = new DemoDbContext(); var account = new Account(); db.Accounts.Add(account); try { db.SaveChanges(); } catch (Exception ex) { throw; } } }
這樣寫 EF 就會賞你個錯誤
如何解決:
- 要解決這個問題,就是乖乖的填寫 Name,但我這邊的需求是要填一筆空字串,這表示我要繞過 EF 的檢查。
- 由於我們的類別是由 EF Tool 所產生的,不應該去動到EF Tool 所產生出來的檔案。因為 EF Tool 所產生的是 partial class,所以我們可以利用這個特性擴充我們所需要的功能,利用 MetadataType + partial class,修改EF的檢查機制,讓測試程式碼成功插入一筆垃圾資料
- 將 Require.AllowEmptyString=true,並再建構函數設定 Name 為空字串
public class AccountMetaData
{
[Required(AllowEmptyStrings = true)]
public string Name { get; set; }
}
[MetadataType(typeof(AccountMetaData))]
public partial class Account
{
public Account()
{
this.Name = "";
}
}
如此一來,便繞過 EF 的檢查..
套用資料庫設定的預設值
如 CreateDate 已經在資料庫設定 getdate(),你想要讓應用程式吃這個設定
由於在 C# 的 DateTime 預設值是 0001/01/01 ,所以 EF 所產生的 SQL 語法也會是那個日期,若要套用 SQL 的預設值可以使用 DatabaseGeneratedOption.Computed,EF 會罷工,不產生這個欄位的 T-SQL 語法
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreateDate { get; set; }
本文出自:http://www.dotblogs.com.tw/yc421206/archive/2015/04/12/151024.aspx
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET