EF 6 Code-First系列文章目錄:
- 1 翻譯系列:什么是Code First(EF 6 Code First 系列)
- 2.翻譯系列:為EF Code-First設置開發環境(EF 6 Code-First系列)
- 3.翻譯系列:EF Code-First 示例(EF 6 Code-First系列)
- 4.翻譯系列:EF 6 Code-First默認約定(EF 6 Code-First系列)
- 5.翻譯系列:EF 6中數據庫的初始化(EF 6 Code-First 系列)
- 6.翻譯系列:EF 6 Code-First中數據庫初始化策略(EF 6 Code-First系列
- 7.翻譯系列:EF 6中的繼承策略(EF 6 Code-First 系列)
- 8.翻譯系列: EF 6中配置領域類(EF 6 Code-First 系列)
- 9.翻譯系列:EF 6以及EF Core中的數據注解特性(EF 6 Code-First系列)
- 9.1 翻譯系列:數據注解特性之----Table【EF 6 Code-First 系列】
- 9.2 翻譯系列:數據注解特性之---Column【EF 6 Code First系列】
- 9.3 翻譯系列:數據注解特性之Key【EF 6 Code-First 系列】
- 9.4 翻譯系列:EF 6以及 EF Core中的NotMapped特性(EF 6 Code-First系列)
- 9.5 翻譯系列:數據注解之ForeignKey特性【EF 6 Code-First系列】
- 9.6 翻譯系列:數據注解之Index特性【EF 6 Code-First系列】
- 9.7 翻譯系列:EF數據注解特性之--InverseProperty【EF 6 Code-First系列】
- 9.8 翻譯系列:數據注解特性之--Required 【EF 6 Code-First系列】
- 9.9 翻譯系列:數據注解特性之--MaxLength 【EF 6 Code-First系列】
- 9.10 翻譯系列:EF數據注解特性之StringLength【EF 6 Code-First系列】
- 9.11 翻譯系列:數據注解特性之--Timestamp【EF 6 Code-First系列】
- 9.12 翻譯系列:數據注解特性之ConcurrencyCheck【EF 6 Code-First系列】
- 10.翻譯系列:EF 6中的Fluent API配置【EF 6 Code-First系列】
- 10.1.翻譯系列:EF 6中的實體映射【EF 6 Code-First系列】
- 10.2.翻譯系列:使用Fluent API進行屬性映射【EF 6 Code-First】
- 11.翻譯系列:在EF 6中配置一對零或者一對一的關系【EF 6 Code-First系列】
- 12.翻譯系列:EF 6 中配置一對多的關系【EF 6 Code-First系列】
- 13.翻譯系列:Code-First方式配置多對多關系【EF 6 Code-First系列】
- 14.翻譯系列:從已經存在的數據庫中生成上下文類和實體類【EF 6 Code-First系列】
- 15.翻譯系列:EF 6中的級聯刪除【EF 6 Code-First 系列】
- 16.翻譯系列:EF 6 Code -First中使用存儲過程【EF 6 Code-First系列】
- 17.翻譯系列:將Fluent API的配置遷移到單獨的類中【EF 6 Code-First系列】
- 18.翻譯系列:EF 6 Code-First 中的Seed Data(種子數據或原始測試數據)【EF 6 Code-First系列】
- 19.翻譯系列:EF 6中定義自定義的約定【EF 6 Code-First約定】
- 20.翻譯系列:Code-First中的數據庫遷移技術【EF 6 Code-First系列】
- 20.1翻譯系列:EF 6中自動數據遷移技術【EF 6 Code-First系列】
- 20.2.翻譯系列:EF 6中基於代碼的數據庫遷移技術【EF 6 Code-First系列】
- 21.翻譯系列:Entity Framework 6 Power Tools【EF 6 Code-First系列】
當你第一次運行Code-First應用程序的時候,EF就會為我們創建數據庫,但是,后面呢,第二次第三次..的時候會是什么情況?是不是每次運行程序的時候,都會創建一個新的數據庫?生產環境中會是什么情況?當你改變你的領域模型的時候,你怎么修改數據庫呢?為了解決這些情況,你需要來使用數據庫初始化策略。
EF 6中,有四種不同的數據庫初始化策略:
- CreateDatabaseIfNotExists:這是默認的數據庫初始化策略。就像它的名稱那樣,如果根據配置,數據庫不存在的話,就會創建數據庫。但是如果你改變模型類,使用這個策略,再運行程序的話,就會拋出一個異常。
- DropCreateDatabaseIfModelChanges:這個策略會在你的模型發生改變的時候,刪除已經存在的數據庫,然后創建一個新的數據庫。所以當你模型改變的時候,不必擔心怎么來維護數據庫對象模式。
- DropCreateDatabaseAlways:就像其名稱所示,這個策略每次你運行程序的時候,都會刪除以及存在的數據庫,而不管你的模型類 是否發生改變。這個策略非常有用,當你每次運行程序,都想要一個新的數據庫的時候。例如:當你在開發程序的時候。使用這個策略比較好。
- 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 }

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屬性,在運行:
看,成功了吧,是不是很爽?我們看看數據庫:
好了,上面就是我們今天學習的全部內容,數據庫初始化策略,有不明白的,可以留言,我會一一回復,謝謝支持。