1. 程式人生 > >Entity Framework——建模建庫

Entity Framework——建模建庫

conf fig codefirst creat -c question 原來 三種 表示

1數據庫初始化策略選擇

三種初始化策略:

1)CreateDatabaseIfNotExists:默認的策略如果數據庫不存在,那麽就創建數據庫。但是如果數據庫存在,而且實體發生了變化,就會出現異常。

2)DropCreateDatabaseIfModelChanges:模型改變時,原來的數據庫會被刪除,自動重新創建一個新的數據庫

3)DropCreateDatabaseAlways:每次運行都會刪除原來的數據庫,然後重新生成數據庫。

4)Null:在Codefirst模式下,當實體結構改變時,運行程序不會自動生成表,改變實體結構與改變表結構互不影響,

上述策略無法應對的問題是:分別改變實體模型和數據庫表結構。即,當使用

CreateDatabaseIfNotExists策略時,修改實體模型會拋異常(The model backing the <Database> context has changed since the database was created

);若使用DropCreateDatabaseIfModelChanges模式,那麽每次運行都會重新生成數據庫,這導致歷史數據丟失,然而提前備份數據這種策略比較麻煩,尤其是系統上線以後。

解決辦法:

采用第四種初始化策略,初次使用codefirst方式創建好數據庫以後,不使用任何數據庫初始化策略,即給Database.SetInitializer

null。

[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_IdEntityOne_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_IdEntityTwosOther_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為關系表,表的屬性只包括兩個表的主鍵。

問題1publications表的數據會大量重復:假設用戶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——建模建庫