原文链接: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=, /// <summary>
/// 女士
/// </summary>
Woman=
}

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=,
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=,
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属性,在运行:

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

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

6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)的更多相关文章

  1. 16.翻译系列:EF 6 Code -First中使用存储过程【EF 6 Code-First系列】

    原文链接:https://www.entityframeworktutorial.net/entityframework6/code-first-insert-update-delete-stored ...

  2. 4.DB Initialization(数据库初始化)[EF Code-First系列]

    前面的例子中,我们已经看到了Code-First自动为我们创建数据库的例子. 这里我们将要学习的是,当初始化的时候,Code-First是怎么决定数据库的名字和服务的呢??? 下面的图,解释了这一切! ...

  3. EF CodeFirst系列(2)---CodeFirst的数据库初始化

    1. CodeFirst的默认约定 1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的一些约定.在CodeFirst模式中,约定指的是根据领域类(如Stu ...

  4. EF CodeFirst 数据库初始化策略

    最近用EF做了几个小东西,了解简单使用后有了深入研究的兴趣,所以想系统的研究一下EF CodeFist的几个要点.下面简单列一下目录 1.1 目录 数据库初始化策略和数据迁移Migration的简单介 ...

  5. EF数据库初始化策略及种子数据的添加

    EF数据库初始化策略及种子数据的添加 CreateDatabaseIfNotExists 判断当前数据库连接字符串对应的数据库是否存在,若不存在则根据代码定义的model进行创建 DropCreate ...

  6. EF CodeFirst简介、默认约定、数据库初始化策略

    CodeFirst 工作流程 创建或修改领域类-->使用数据注解或者Fluent API来配置领域类-->使用自动数据库迁移技术或者基于代码的数据库迁移技术来创建数据库. CodeFirs ...

  7. Entity FrameWork Code First 之 MVC4 数据库初始化策略用法

    通过启用迁移和更新数据库可以很容易的生成一张表.但是对数据库修改之后,通过数据迁移就没那么好实现了. 这里用到数据库生成策略,进行对数据库操作: 一.3种主要数据库生成策略 1 CreateDatab ...

  8. EF Code-First 学习之旅 数据库初始化

    1.CreateDatabaseIfNotExists: 2.DropCreateDatabaseIfModelChanges: 3.DropCreateDatabaseAlways: 4.Custo ...

  9. EF Code-First 学习之旅 数据库初始化 (二)

    Context类的基类构造函数有如下的参数 1.无参数 如果没有给基类构造函数添加参数,它会在local SQLEXPRESS server创建数据库,名为{Namespace}.{Context c ...

随机推荐

  1. BZOJ 3771 Triple FFT+容斥原理

    解析: 这东西其实就是指数型母函数? 所以刚开始读入的值我们都把它前面的系数置为1. 然后其实就是个多项式乘法了. 最大范围显然是读入的值中的最大值乘三,对于本题的话是12W? 用FFT优化的话,达到 ...

  2. 最短路径问题 HDU3790 (dijkstra)

    基础的dijkstra问题  加上了花费 #include<bits/stdc++.h> using namespace std; ][][]; ];]; #define INF 9999 ...

  3. Free DIY Tour HDU1224

    一道很好的dfs加储存路径的题目  :路径保存:每次dfs都存i 当大于max时 将临时数组保存到答案数组 并不是当 当前值大于最大值时更新路径 还要加上一个条件:能回去 #include<bi ...

  4. Selenium 获取文本信息方法+select(定位)

    1.通过先定位到具体的元素然后通过text方法获取文本信息,如获取控件名称等 driver.find_element_by_xpath("//div[/h1").text 2.直接 ...

  5. ADI SHARC 学习之PLL

    PLL Block Diagram             Power Management Registers (PMCTL, PMCTL1)The following sections descr ...

  6. 使用 Spring Boot 搭建一套增删改查(无多余代码)

    前言 这是我学习 Spring Boot 的第三篇文章,终于可以见到效果了.错过的同学可以看看之前的文章 我们为什么要学习 Spring Boot Spring Boot 入门详细分析 在入门的基础上 ...

  7. 【RAY TRACING THE REST OF YOUR LIFE 超详解】 光线追踪 3-4 基于重要性采样的材质初探

     Preface 我们今天来把第三本书从开局到现在讲的一大堆理论运用到我们的框架中,那么今天我们首先将原始的材质改为基于重要性采样原理的材质 这一篇是代码工程中进行MC理论应用的初步尝试篇  Read ...

  8. 系统windows版本修改

    系统基本信息修改 系统windows版本修改 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com E-mail: 313134555 @qq.com ...

  9. C语言---斐波那契问题

      最近学习了一个叫递归的概念,里面最著名的一个例子就是斐波那契问题,觉得很有意思,就来实现一下: 什么是斐波那契数列   斐波那契数列,又称黄金分割数列,值得这样一个数列:0.1.1.3.5.8.1 ...

  10. HDU.2829.Lawrence(DP 斜率优化)

    题目链接 \(Description\) 给定一个\(n\)个数的序列,最多将序列分为\(m+1\)段,每段的价值是这段中所有数两两相乘的和.求最小总价值. \(Solution\) 写到这突然懒得写 ...