6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

释放双眼,带上耳机,听听看~!

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

       当你第一次运行Code-First应用程序的时候,EF就会为我们创建数据库,但是,后面呢,第二次第三次..的时候会是什么情况?是不是每次运行程序的时候,都会创建一个新的数据库?生产环境中会是什么情况?当你改变你的领域模型的时候,你怎么修改数据库呢?为了解决这些情况,你需要来使用数据库初始化策略。

       EF 6中,有四种不同的数据库初始化策略:

  1. CreateDatabaseIfNotExists:这是默认的数据库初始化策略。就像它的名称那样,如果根据配置,数据库不存在的话,就会创建数据库。但是如果你改变模型类,使用这个策略,再运行程序的话,就会抛出一个异常。
  2. DropCreateDatabaseIfModelChanges:这个策略会在你的模型发生改变的时候,删除已经存在的数据库,然后创建一个新的数据库。所以当你模型改变的时候,不必担心怎么来维护数据库对象模式。
  3. DropCreateDatabaseAlways:就像其名称所示,这个策略每次你运行程序的时候,都会删除以及存在的数据库,而不管你的模型类 是否发生改变。这个策略非常有用,当你每次运行程序,都想要一个新的数据库的时候。例如:当你在开发程序的时候。使用这个策略比较好。
  4. Custom DB Initializer: 如果上面的策略不满足你的需求或者数据库初始化的时候,你想额外做一些其他的处理的时候, 你就可以创建你自己的数据库初始化策略。

为了使用上面提到的4个数据库初始化策略,你可以在上下文类中,使用Database类,例如下面代码:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

你如果想使用自定义的数据库初始化策略,就可以继承上面三个中的其中一个策略,例如:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

在上面的代码中,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>

关闭数据库初始化策略

你可以为应用程序关闭数据库初始化策略。假设你不想丢失生产环境的数据,你可以按照下面的设置,关闭数据库初始化策略:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

同样你可以通过,配置文件来关闭数据库初始化策略:

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

 

 好了,理论介绍完了,我们何不动手实践一下呢?

这里我创建一个名称为EFDbInitializer控制台应用程序,安装好EF 6,来验证今天所学:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

为了简单起见,我只创建一个Student类,和一个上下文类:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 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
6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 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(); } }

运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

说明创建数据库成功了,里面我们插入了一条记录。我们看看:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

从图中可以看到,EF默认生成的表名称就是实体名称+一个后缀s.默认映射实体中所有的属性。【注意:只映射有get;set;的属性哦

现在,我们用这个数据库,来验证一下今天所学:

 修改上下文类:加一句代码,如下标识:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

然后运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

看到又成功了,注意,数据库中之前有一条数据,现在我们应用了这个DropCreateDatabaseAlways策略,那么数据库中还是会只有一条数据的,不信我们看:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

在来验证一下,CreateDatabaseIfNotExists策略,修改一下上下文类中的代码:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

 成功了,这个时候,请注意:数据库中应该是有两条数据的,因为数据库已经存在了,应用这个策略之后,EF不会再删除数据库,重新创建。我们看看:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

再验证一下DropCreateDatabaseIfModelChanges策略,

我们修改一下Student实体,新增一个Password字段。

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

 然后修改一下上下文类:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

看到了么,又成功了,这个时候,数据库应该只有一条语句,因为我们模型改变了,Students表应该还多了一个Password列。我们看看:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

好了,现在我们来验证一下,自定义的数据库初始化策略。

创建一个自定义的数据库初始化策略类,继承自: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属性。

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

在修改一下测试代码:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

修改一下上下文类的代码:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

运行程序:

 6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

 

 成功了,我们看看数据库,这个时候数据库有数据么,你们猜猜???有数据的话,有几条数据呢???答案是一条数据,就是我在自定义数据库初始化策略中添加的一条。

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

 

 现在,我们来验证一下,我们如何在配置文件中,配置我们的数据库初始化策略:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

我的项目的命名空间是:EFDbInitializer,配置的要点就是DatabaseInitializerForType 命名空间.上下文类,命名空间,value值就是:命名空间.自定义的数据库初始化策略类,命名空间。

然后修改一下上下文类:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

看看数据库:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

不相信配置文件配置的这个策略被执行了的话,我们删除数据库,然后修改实体看看:

1.删除数据库

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

2.修改一下实体:注释QQ属性

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

3.修改上下文类:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

配置文件还是这样:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

看看数据库发生了什么:可以看到QQ列不见了,还是有一条数据,我们在自定义类中添加的,说明配置文件成功了配置数据库初始化策略。

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

好了,最后看看,怎么关闭数据库初始化策略吧:

1.取消注释QQ属性:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

 2.修改自定义的初始化策略类:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

3.运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

看,报错了哦,这是因为我们使用CreateDatabaseIfNotExists策略的时候,如果实体模型发生改变的话,就会抛异常,这个异常可以通过,数据库迁移技术解决,还可以通过关闭数据库初始化策略解决,这里我采用第二种解决方法。

关闭数据库策略。

修改上下文类:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

运行程序:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

咦,怎么还是报错呢??原来配置文件中,还没注释掉呢,我们注释一下:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

 再运行,咦,又报错了,这是错误不一样哦,QQ列名无效,哦,明白了, 关闭策略之后,我们就不会再创建数据库了,【这个时候,我们自定义的策略类是CreateDatabaseIfNotExists,数据库已经存在就不会删除创建】,然而QQ这一个属性还在Student实体中,EF就会要映射到数据库,这就冲突了,我们注释QQ属性。

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 注释QQ属性,在运行:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

看,成功了吧,是不是很爽?我们看看数据库:

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)

 

好了,上面就是我们今天学习的全部内容,数据库初始化策略,有不明白的,可以留言,我会一一回复,谢谢支持。

给TA打赏
共{{data.count}}人
人已打赏
随笔日记

全通教育:拟15亿元收购巴九灵96%股权 深交所火速发问询函

2020-11-9 4:07:14

随笔日记

大数据技术之_16_Scala学习_07_数据结构(上)-集合

2020-11-9 4:07:16

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索