Entity Framework——建模建庫
1數據庫初始化策略選擇
三種初始化策略:
1)CreateDatabaseIfNotExists:默認的策略。如果數據庫不存在,那麽就創建數據庫。但是如果數據庫已存在,而且實體發生了變化,就會出現異常。
2)DropCreateDatabaseIfModelChanges:模型改變時,原來的數據庫會被刪除,自動重新創建一個新的數據庫。
3)DropCreateDatabaseAlways:每次運行都會刪除原來的數據庫,然後重新生成數據庫。
4)Null:在Codefirst模式下,當實體結構改變時,運行程序不會自動生成表,改變實體結構與改變表結構互不影響,
上述策略無法應對的問題是:分別改變實體模型和數據庫表結構。即,當使用
);若使用DropCreateDatabaseIfModelChanges模式,那麽每次運行都會重新生成數據庫,這導致歷史數據丟失,然而提前備份數據這種策略比較麻煩,尤其是系統上線以後。
解決辦法:
采用第四種初始化策略,初次使用codefirst方式創建好數據庫以後,不使用任何數據庫初始化策略,即給Database.SetInitializer傳
[DbConfigurationType(typeof(MySqlEFConfiguration))] public class HY_WebApiContext : DbContext { public HY_WebApiContext(): base("name=HY_WebApiContext") { Database.SetInitializer<HY_WebApiContext>(null); } ...... }
2實體關系與依賴默認規則創建的表關系
Codefirst模式下,實體與表之間的映射,隨實體關系的不同而不同。
1)實體之間為一對一關系
實體
public class EntityOne { public int Id { get; set; } public string FieldEntityOne { get; set; } public EntityTwo EntityTwo { get; set; } } public class EntityTwo { public int Id { get; set; } public string FieldEntityTwo { get; set; } }
表結構
entityones,其中EntityTwo_Id為外鍵。
EntityTwo
2)實體間的一對多關系
實體
public class EntityOne { public int Id { get; set; } public string FieldEntityOne { get; set; } public List<EntityTwo> EntityTwos { get; set; } } public class EntityTwo { public int Id { get; set; } public string FieldEntityTwo { get; set; } }
表結構
entityones
entitytwoes,其中EntityOne_Id是外鍵
3)實體間的多對多關系
實體
public class EntityOne { public int Id { get; set; } public string FieldEntityOne { get; set; } public List<EntityTwo> EntityTwos { get; set; } } public class EntityTwo { public int Id { get; set; } public string FieldEntityTwo { get; set; } public List<EntityOne> EntityOnes { get; set; } }
表結構
Codefirst模式下,兩個實體間的多對多關系,映射為三張表,其中一張表表示實體間的聯系。
entityones
entitytwoes
entitytwoentityones,其中EntityTwo_Id和EntityOne_Id是外鍵,這兩個外鍵構成了改表的復合主鍵。
4)實體包含類型相同的兩個或多個名稱不同的導航屬性
實體
public class EntityOne { public int Id { get; set; } public string FieldEntityOne { get; set; } public EntityTwo EntityTwos { get; set; } public EntityTwo EntityTwosOther { get; set; } } public class EntityTwo { public int Id { get; set; } public string FieldEntityTwo { get; set; } }
表
Entityones,其中EntityTwos_Id、EntityTwosOther_Id是外鍵。
entitytwoes
3為關系創建實體:
一個用戶可以訂閱多種出版物,一種出版物可被多個用戶訂閱,實體建模如下:
public class Publication { public int Id { get; set; } public virtual ICollection<User> Users { get; set; } ...... } public class User { public int Id { get; set; } public virtual ICollection<Publication> Publications { get; set; } ...... }
EF框架對上述多對多關系的默認處理方式為生成三張表:publications,user,publicationusers
其中publicationusers為關系表,表的屬性只包括兩個表的主鍵。
問題1:publications表的數據會大量重復:假設用戶A訂閱了電子學報,publications表裏會有一條關於電子學報的記錄,當用戶B也訂閱電子學報的時候,又會將這條數據插入publications表,如此等等。
解決方案:
每次向publications表插入記錄時,先在表中查找待插入的刊物是否存在,如果存在就不插入,只更新publicationusers表。
問題2:雖然使用上面的方法可以解決這個問題,但用戶何時訂閱了一種刊物,這類信息沒有被記錄下來。
解決方案:
添加一個實體,表達publications,user這兩個實體之間的關系,實體如下:
public class Publication { public int Id { get; set; } ...... } public class User { public int Id { get; set; } ...... } public class PublicationUser { public int Id { get; set; } /// <summary> /// 出版物 /// </summary> public Publication Publication { get; set; } /// <summary> /// 所屬用戶 /// </summary> public User User { get; set; } /// <summary> /// 記錄插入時間 /// </summary> public DateTime InsertTime { get; set; } /// <summary> /// 記錄修改時間 /// </summary> public DateTime UpdateTime { get; set; } }
經上述處理後,EF仍然生成三張表publications,user,publicationusers,與之前不同的是publicationusers表中多了Id ,InsertTime ,UpdateTime 這三個字段,同時去掉了publications,user其中的導航屬性,這樣的設計滿足需求,且無冗余。那麽經過這樣的修改後,每一個PublicationUser實例對應了表中的一條記錄。
Entity Framework——建模建庫