《看我72變》是蔡依林的一首歌,“我要洗心革面,人定可以勝天,夢想近在眼前。。。”
在代碼世界中,有一種常見的“變” —— 類型轉變。這篇文章分享的就是如何通過類型轉變,解決Entity Framework(5.0之前的版本)中枚舉類型(實體)與 tinyint(數據庫字段類型)的映射問題。
對於需要進行持久化的枚舉類型,我們通常在數據庫表中建立一個對應的tinyint類型的字段。
如果我們使用Entity Framework作為ORM,將面臨兩個問題:
1. EF不支持枚舉類型的直接映射(5.0之前的版本)
2. 對於tinyint數據庫類型,不管對應的實體屬性定義的是什么類型,EF始終映射為byte類型。
相應的解決方法也不難:
1. 給實體增加一個“中間人”屬性,與數據庫中對應的字段進行映射,然后再轉換為枚舉類型。
2. 將這個“中間人”屬性定義為byte類型。
於是就有了下面的代碼:
public class BlogCategory { public CategoryType CategoryType { get; set; }
public byte CategoryTypeByte { get; set; } }
BlogCategory.CategoryType是枚舉類型的屬性,是代碼中實際訪問的屬性;BlogCategory.CategoryTypeByte是增加的“中間人”屬性,專用於映射數據庫中tinyint類型的字段。
隨之,難題出現了,如何在枚舉類型與bype類型之間進行轉換呢?在讀取BlogCategory.CategoryType屬性時,需要將byte轉換為枚舉;在寫入BlogCategory.CategoryType屬性時,需要將枚舉轉換為byte。
枚舉類型可以方便地轉換為int類型,但int類型是32位的(4個byte)。也就是說,這兩者尺碼不一樣,大轉小,要減肥;小轉大,要增胖。
對於類型轉換安全問題,我們無需擔心,因為數據庫中是tinyint類型,數據的長度不會超過1個byte。
那如何轉換呢?
.NET提供了一個強大的轉換器 —— System.BitConverter,讓我們來看看如何通過它實現72變。
1. 大轉小,減肥,枚舉轉byte。
public BlogCategoryType CategoryType { set { CategoryTypeByte = BitConverter.GetBytes((int)value)[0]; } }
將枚舉轉換為int,再將int轉換為byte數組,然后取第一個元素。
2. 小轉大,增胖,byte轉枚舉。
public BlogCategoryType CategoryType { get { return (BlogCategoryType)BitConverter.ToInt32( new byte[] { CategoryTypeByte, 0x0, 0x0, 0x0 }, 0); } }
增加三個值為0的byte,與CategoryTypeByte組合為長度為4的byte數組(因為int類型的需要),然后將這個byte數組轉換為int類型。
注:該解決方法已通過臨床驗證,確實有療效,請放心使用!