6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列)
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=, /// <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系列)的更多相关文章
- 16.翻译系列:EF 6 Code -First中使用存储过程【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/entityframework6/code-first-insert-update-delete-stored ...
- 4.DB Initialization(数据库初始化)[EF Code-First系列]
前面的例子中,我们已经看到了Code-First自动为我们创建数据库的例子. 这里我们将要学习的是,当初始化的时候,Code-First是怎么决定数据库的名字和服务的呢??? 下面的图,解释了这一切! ...
- EF CodeFirst系列(2)---CodeFirst的数据库初始化
1. CodeFirst的默认约定 1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的一些约定.在CodeFirst模式中,约定指的是根据领域类(如Stu ...
- EF CodeFirst 数据库初始化策略
最近用EF做了几个小东西,了解简单使用后有了深入研究的兴趣,所以想系统的研究一下EF CodeFist的几个要点.下面简单列一下目录 1.1 目录 数据库初始化策略和数据迁移Migration的简单介 ...
- EF数据库初始化策略及种子数据的添加
EF数据库初始化策略及种子数据的添加 CreateDatabaseIfNotExists 判断当前数据库连接字符串对应的数据库是否存在,若不存在则根据代码定义的model进行创建 DropCreate ...
- EF CodeFirst简介、默认约定、数据库初始化策略
CodeFirst 工作流程 创建或修改领域类-->使用数据注解或者Fluent API来配置领域类-->使用自动数据库迁移技术或者基于代码的数据库迁移技术来创建数据库. CodeFirs ...
- Entity FrameWork Code First 之 MVC4 数据库初始化策略用法
通过启用迁移和更新数据库可以很容易的生成一张表.但是对数据库修改之后,通过数据迁移就没那么好实现了. 这里用到数据库生成策略,进行对数据库操作: 一.3种主要数据库生成策略 1 CreateDatab ...
- EF Code-First 学习之旅 数据库初始化
1.CreateDatabaseIfNotExists: 2.DropCreateDatabaseIfModelChanges: 3.DropCreateDatabaseAlways: 4.Custo ...
- EF Code-First 学习之旅 数据库初始化 (二)
Context类的基类构造函数有如下的参数 1.无参数 如果没有给基类构造函数添加参数,它会在local SQLEXPRESS server创建数据库,名为{Namespace}.{Context c ...
随机推荐
- 2015 Benelux Algorithm Programming Contest I- Interesting Integers
题目大意:给你一个数字n(n<=1e9) ,让你求一个能包含这个数的斐波那契数列的第一项a 和第二项b,找出b最小的那个. 帮我复习了一下扩展欧几里得.... 思路:a,b,a+b,a+2b…… ...
- 【Java】 剑指offer(6) 重建二叉树
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的 ...
- 010 处理模型数据(ModelAndView,Map Model,@SessionAttributes)
1.处理数据模型 SpringMVC提供了几种途径出书模型数据 二:ModelAndView 1.介绍 2.index <%@ page language="java" co ...
- python中简单文件的输入三种方式
最近在自学python,简单的总结了一下文件的输入的方式. 1. f=open("foo.txt") line=f.readline() while line: print(lin ...
- mysql 用户表结构设计,第三方登录
说起用户表,大概是每个应用/网站立项动工(码农们)考虑的第一件事情.用户表结构的设计,算是整个后台架构的基石.如果基石不稳,待到后面需求跟进了发现不能应付,回过头来反复修改用户表,要大大小小作改动的地 ...
- Laravel 5 插入数据后返回主键ID
方法一: $info = DB::table('表名')->insertGetId(['imgName' => $fileName]);//图片名入库后返回添加数据行的主键ID 方法二:( ...
- BroadcastReceiver广播接受者
广播接收器的两种注册方式: 1)动态注册:在代码中注册,创建一个IntentFilter(意图过滤器)对象,设置想要就收的广播,在onCreate()方法中通过调用registerReceiver() ...
- macOS下通过docker在局域网成功访问mysql5.6数据库
1.获取mysql镜像 docker pull mysql:5.6 注意:此处之所以获取mysql5.6是因为mysql5.7在centos7中启动可能会报错, 2.查看镜像列表 docker ima ...
- poj3259 Wormholes (判负环)【spfa】(模板)
<题目链接> 题目大意: John的农场里N块地,M条路连接两块地,W个虫洞,虫洞是一条单向路,会在你离开之前把你传送到目的地,就是当你过去的时候时间会倒退Ts.我们的任务是知道会不会在从 ...
- HDU 1051 Wooden Sticks 造木棍【贪心】
题目链接>>> 转载于:https://www.cnblogs.com/Action-/archive/2012/07/03/2574800.html 题目大意: 给n根木棍的长度 ...