6.翻譯系列:EF 6 Code-First中數據庫初始化策略(EF 6 Code-First系列)


       原文鏈接:http://www.entityframeworktutorial.net/code-first/database-initialization-strategy-in-code-first.aspx

 

EF 6 Code-First系列文章目錄:

 

   

   當你第一次運行Code-First應用程序的時候,EF就會為我們創建數據庫,但是,后面呢,第二次第三次..的時候會是什么情況?是不是每次運行程序的時候,都會創建一個新的數據庫?生產環境中會是什么情況?當你改變你的領域模型的時候,你怎么修改數據庫呢?為了解決這些情況,你需要來使用數據庫初始化策略。

       EF 6中,有四種不同的數據庫初始化策略:

  1. CreateDatabaseIfNotExists:這是默認的數據庫初始化策略。就像它的名稱那樣,如果根據配置,數據庫不存在的話,就會創建數據庫。但是如果你改變模型類,使用這個策略,再運行程序的話,就會拋出一個異常。
  2. DropCreateDatabaseIfModelChanges:這個策略會在你的模型發生改變的時候,刪除已經存在的數據庫,然后創建一個新的數據庫。所以當你模型改變的時候,不必擔心怎么來維護數據庫對象模式。
  3. DropCreateDatabaseAlways:就像其名稱所示,這個策略每次你運行程序的時候,都會刪除以及存在的數據庫,而不管你的模型類 是否發生改變。這個策略非常有用,當你每次運行程序,都想要一個新的數據庫的時候。例如:當你在開發程序的時候。使用這個策略比較好。
  4. Custom DB Initializer: 如果上面的策略不滿足你的需求或者數據庫初始化的時候,你想額外做一些其他的處理的時候, 你就可以創建你自己的數據庫初始化策略。

為了使用上面提到的4個數據庫初始化策略,你可以在上下文類中,使用Database類,例如下面代碼:

你如果想使用自定義的數據庫初始化策略,就可以繼承上面三個中的其中一個策略,例如:

在上面的代碼中,SchoolDBInitiallizer就是一個自定義的數據庫初始化策略類,它繼承自CreateDatabaseIfNotExists。這種做法,將初始化策略代碼從上下文類中分離開來了。

 在配置文件中創建數據庫初始化策略

你同樣可以在配置文件中,設置數據庫初始化策略。例如,下面代碼在配置文件中設置了默認的初始化策略--CreateDatabaseIfNotExists。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
    <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer" value="System.Data.Entity.DropCreateDatabaseAlways`1[[SchoolDataLayer.SchoolDBContext, SchoolDataLayer]], EntityFramework" />
    </appSettings>
</configuration>

你可以按照下面設置自定義的初始化策略:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>    
    <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer" value="SchoolDataLayer.SchoolDBInitializer, SchoolDataLayer" />
    </appSettings>
</configuration>

關閉數據庫初始化策略

你可以為應用程序關閉數據庫初始化策略。假設你不想丟失生產環境的數據,你可以按照下面的設置,關閉數據庫初始化策略:

同樣你可以通過,配置文件來關閉數據庫初始化策略:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>    
    <add key="DatabaseInitializerForType SchoolDataLayer.SchoolDBContext, SchoolDataLayer" value="Disabled" />
    </appSettings>
</configuration>

 

 好了,理論介紹完了,我們何不動手實踐一下呢?

這里我創建一個名稱為EFDbInitializer控制台應用程序,安裝好EF 6,來驗證今天所學:

為了簡單起見,我只創建一個Student類,和一個上下文類:

 public class Student { /// <summary>
        /// 學生ID /// </summary>
        public int StudentID { get; set; } /// <summary>
        /// 學生姓名 /// </summary>
        public string StudentName { get; set; } /// <summary>
        /// 學生年齡 /// </summary>
        public int Age { get; set; } /// <summary>
        /// 郵箱 /// </summary>
        public string Email { get; set; } /// <summary>
        /// 性別 /// </summary>
        public Gender Gender { get; set; } } public enum Gender { /// <summary>
        /// 男士 /// </summary>
        Man=0, /// <summary>
        /// 女士 /// </summary>
        Woman=1 }
Student
 public class EFDbContext:DbContext { public EFDbContext() : base("name=Constr") { } public DbSet<Student> StuentTable { get; set; } }
上下文類的代碼

數據庫配置信息:

 <!--數據庫連接字符串-->
  <connectionStrings>
    <add name="Constr" connectionString="server=.;database=EFInitiallizerDB;uid=sa;pwd=Password_1" providerName="System.Data.SqlClient"/>
  </connectionStrings>

測試代碼:

 class Program { static void Main(string[] args) { using (var db = new EFDbContext()) { Student stuModel = new Student() { StudentName="曹雪芹", Age=18, Gender=Gender.Man, Email="caoxueqin@163.com" }; db.Entry(stuModel).State = EntityState.Added; db.SaveChanges(); } Console.WriteLine("success"); Console.ReadKey(); } }

運行程序:

說明創建數據庫成功了,里面我們插入了一條記錄。我們看看:

從圖中可以看到,EF默認生成的表名稱就是實體名稱+一個后綴s.默認映射實體中所有的屬性。【注意:只映射有get;set;的屬性哦

現在,我們用這個數據庫,來驗證一下今天所學:

 修改上下文類:加一句代碼,如下標識:

然后運行程序:

看到又成功了,注意,數據庫中之前有一條數據,現在我們應用了這個DropCreateDatabaseAlways策略,那么數據庫中還是會只有一條數據的,不信我們看:

 

在來驗證一下,CreateDatabaseIfNotExists策略,修改一下上下文類中的代碼:

運行程序:

 

 成功了,這個時候,請注意:數據庫中應該是有兩條數據的,因為數據庫已經存在了,應用這個策略之后,EF不會再刪除數據庫,重新創建。我們看看:

再驗證一下DropCreateDatabaseIfModelChanges策略,

我們修改一下Student實體,新增一個Password字段。

 

 然后修改一下上下文類:

運行程序:

看到了么,又成功了,這個時候,數據庫應該只有一條語句,因為我們模型改變了,Students表應該還多了一個Password列。我們看看:

 

好了,現在我們來驗證一下,自定義的數據庫初始化策略。

創建一個自定義的數據庫初始化策略類,繼承自:DropCreateDatabaseIfModelChanges

 /// <summary>
    /// 自定義數據庫初始化策略類 /// </summary>
   public class CustomeDBInit: DropCreateDatabaseIfModelChanges<EFDbContext> { protected override void Seed(EFDbContext context) { Student stuModel = new Student() { StudentName="貂蟬", Age=20, Gender=Gender.Woman, Password="*******", Email="diaochan@163.com" }; context.Entry(stuModel).State = EntityState.Added; context.SaveChanges(); } }

然后修改Student實體,新增一個QQ屬性。

在修改一下測試代碼:

 

修改一下上下文類的代碼:

 

運行程序:

 

 

 

 成功了,我們看看數據庫,這個時候數據庫有數據么,你們猜猜???有數據的話,有幾條數據呢???答案是一條數據,就是我在自定義數據庫初始化策略中添加的一條。

 

 

 現在,我們來驗證一下,我們如何在配置文件中,配置我們的數據庫初始化策略:

我的項目的命名空間是:EFDbInitializer,配置的要點就是DatabaseInitializerForType 命名空間.上下文類,命名空間,value值就是:命名空間.自定義的數據庫初始化策略類,命名空間。

然后修改一下上下文類:

運行程序:

看看數據庫:

不相信配置文件配置的這個策略被執行了的話,我們刪除數據庫,然后修改實體看看:

1.刪除數據庫

2.修改一下實體:注釋QQ屬性

3.修改上下文類:

配置文件還是這樣:

運行程序:

看看數據庫發生了什么:可以看到QQ列不見了,還是有一條數據,我們在自定義類中添加的,說明配置文件成功了配置數據庫初始化策略。

 

好了,最后看看,怎么關閉數據庫初始化策略吧:

1.取消注釋QQ屬性:

 

 2.修改自定義的初始化策略類:

3.運行程序:

看,報錯了哦,這是因為我們使用CreateDatabaseIfNotExists策略的時候,如果實體模型發生改變的話,就會拋異常,這個異常可以通過,數據庫遷移技術解決,還可以通過關閉數據庫初始化策略解決,這里我采用第二種解決方法。

關閉數據庫策略。

修改上下文類:

運行程序:

咦,怎么還是報錯呢??原來配置文件中,還沒注釋掉呢,我們注釋一下:

 

 再運行,咦,又報錯了,這是錯誤不一樣哦,QQ列名無效,哦,明白了, 關閉策略之后,我們就不會再創建數據庫了,【這個時候,我們自定義的策略類是CreateDatabaseIfNotExists,數據庫已經存在就不會刪除創建】,然而QQ這一個屬性還在Student實體中,EF就會要映射到數據庫,這就沖突了,我們注釋QQ屬性。

 注釋QQ屬性,在運行:

看,成功了吧,是不是很爽?我們看看數據庫:

 

好了,上面就是我們今天學習的全部內容,數據庫初始化策略,有不明白的,可以留言,我會一一回復,謝謝支持。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM