EF中 Code-First 方式的数据库迁移
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/
系列目录:
- Relationship in Entity Framework Using Code First Approach With Fluent API【【使用EF Code-First方式和Fluent API来探讨EF中的关系】】
- Code First Migrations with Entity Framework【使用EF 做数据库迁移】
- CRUD Operations Using Entity Framework 5.0 Code First Approach in MVC【在MVC中使用EF 5.0做增删查改】
- CRUD Operations Using the Repository Pattern in MVC【在MVC中使用仓储模式,来做增删查改】
- CRUD Operations Using the Generic Repository Pattern and Unit of Work in MVC【在MVC中使用泛型仓储模式和工作单元来做增删查改】
- CRUD Operations Using the Generic Repository Pattern and Dependency Injection in MVC【在MVC中使用泛型仓储模式和依赖注入,来做增删查改】
前面的文章中,学习了EF 中的几种关系,一对一,一对多,多对多。但是相信大家肯定会有疑问:
1.我难道每次都要创建数据库么?
2.我怎么样从已经存在的表中,添加字段和移除字段呢?
3.当我向表中,添加字段或者移除字段,我怎么来避免丢失数据呢?
4.当数据库发生改变的时候,我怎么获取到创建数据库的脚本呢?
不用着急,这篇文章,我会向大家一一讲到:
首先,说说我们为什么要使用数据库迁移技术吧,因为我们的实体总是变动地很频繁,在上篇文章中,我们使用了数据库初始化策略来做,也就是每次当数据库不存在的时候,就创建数据库【类似还有几种初始化策略】,然而,当你的实体改变的时候,在使用这个策略,EF就会报错。而数据库迁移技术就可以帮到我们,我们不用每次都创建数据库。并且数据库迁移技术还可以为我们设置初始化的数据。
先看看项目结构吧:
我们需要建2个类库项目,还有一个控制台的程序:
Student类:
![](https://common.cnblogs.com/images/copycode.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Core
{
public class Student
{
public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; }
}
}
![](https://common.cnblogs.com/images/copycode.gif)
StudentMap类:
![](https://common.cnblogs.com/images/copycode.gif)
using EF.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Ef.Data
{
public class StudentMap:EntityTypeConfiguration<Student>
{
public StudentMap()
{
this.HasKey(s => s.ID);
this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(s => s.Name).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();
this.Property(s => s.Sex).HasColumnType("nvarchar").IsRequired();
this.Property(s => s.Age).IsRequired(); this.ToTable("Students");
}
}
}
![](https://common.cnblogs.com/images/copycode.gif)
EF上下文类:
![](https://common.cnblogs.com/images/copycode.gif)
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Ef.Data
{
public class EFDbContext:DbContext
{
public EFDbContext()
: base("name=DbConnectionString")
{ } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new StudentMap());
//base.OnModelCreating(modelBuilder);
}
}
}
![](https://common.cnblogs.com/images/copycode.gif)
数据库连接字符串:【在EF.Data的配置文件和控制台的项目的配置文件中都要写:】另外注意:这两个项目需要引入EF Server. 代表本机
<connectionStrings>
<add name="DbConnectionString" connectionString="Server=.;database=StudentEFDB;uid=sa;pwd=Password_1" providerName="System.Data.SqlClient" />
</connectionStrings>
connectionString=“Server=.;Database=AppsDB;Trusted_Connection=True” 也可以
控制台中:
![](https://common.cnblogs.com/images/copycode.gif)
using Ef.Data;
using EF.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.App
{
public class Program
{ static void Main(string[] args)
{
Console.WriteLine("你好,请输入姓名:");
string name = Console.ReadLine().Trim();
Console.WriteLine("请输入年龄:");
int result = 0;
//转换成功,result是正确的结果
if (!int.TryParse(Console.ReadLine().Trim(), out result))
{
Console.WriteLine("请输入正确格式的年龄");
return;
}
Console.WriteLine("请输入你的性别:");
string sex = Console.ReadLine(); using(var db=new EFDbContext())
{
Student model = new Student()
{
Name = name,
Sex = sex,
Age = result }; //db.Set<Student>().Add(model);或者下面的
db.Entry(model).State = System.Data.Entity.EntityState.Added;
db.SaveChanges(); }
Console.Write("Success!");
Console.ReadKey(); }
}
}
![](https://common.cnblogs.com/images/copycode.gif)
运行之后,写入数据。
看下数据库中的数据:
好了,这就完成了第一阶段的准备工作:现在我们需要在Student实体中加一个字段Email,项目做一下变动:
![](https://common.cnblogs.com/images/copycode.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Core
{
public class Student
{
public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } public string Email { get; set; }
}
}
![](https://common.cnblogs.com/images/copycode.gif)
![](https://common.cnblogs.com/images/copycode.gif)
using EF.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Ef.Data
{
public class StudentMap:EntityTypeConfiguration<Student>
{
public StudentMap()
{
this.HasKey(s => s.ID);
this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(s => s.Name).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();
this.Property(s => s.Sex).HasColumnType("nvarchar").IsRequired();
this.Property(s => s.Age).IsRequired();
this.Property(s => s.Email).IsRequired(); this.ToTable("Students");
}
}
}
![](https://common.cnblogs.com/images/copycode.gif)
![](https://common.cnblogs.com/images/copycode.gif)
using Ef.Data;
using EF.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.App
{
public class Program
{ static void Main(string[] args)
{
Console.WriteLine("你好,请输入姓名:");
string name = Console.ReadLine().Trim();
Console.WriteLine("请输入年龄:");
int result = 0;
//转换成功,result是正确的结果
if (!int.TryParse(Console.ReadLine().Trim(), out result))
{
Console.WriteLine("请输入正确格式的年龄");
return;
}
Console.WriteLine("请输入你的性别:");
string sex = Console.ReadLine(); Console.WriteLine("请输入你的Email:");
string email = Console.ReadLine(); using(var db=new EFDbContext())
{
Student model = new Student()
{
Name = name,
Sex = sex,
Age = result,
Email=email }; //db.Set<Student>().Add(model);或者下面的
db.Entry(model).State = System.Data.Entity.EntityState.Added;
db.SaveChanges(); }
Console.Write("Success!");
Console.ReadKey(); }
}
}
![](https://common.cnblogs.com/images/copycode.gif)
运行之后:报错,很正常嘛,这肯定报错,因为我们的实体改了。。
怎么办呢??别着急,我们来启用数据库迁移技术:
在程序包控制台中输入:
Enable-Migrations
接着按回车键,在项目中就会生成Migration文件夹,自己去看看里面有啥东东吧。
然后打开Configuration类:修改一下代码:(必须把DbMigrationsConfiguration的参数改成自己程序里的DbContext的namespace+实际类名)
接着在程序包管理器控制台中输入:
Update-Database -Verbose
好了,现在运行一下项目吧:
看到了么,到这里就没报错了。运行完之后,我们看下数据库中的数据:
可以看到之前的数据也在,也就是数据没有丢失。是不是很神奇呢???
总结:这两篇文章总结了EF的一些使用,希望你喜欢。
题外篇:这里是使用EF中的数据库迁移技术。我们就可以随时随地的添加删除字段。而不用手动去删除数据库,那样会丢失数据。
现在,我就想不用数据库迁移呢?
我删掉之前生成的Migration文件夹【包括里面的类】,然后修改代码【删除刚才添加的Email字段】:
![](https://common.cnblogs.com/images/copycode.gif)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.Core
{
public class Student
{
public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public string Sex { get; set; } // public string Email { get; set; }
}
}
![](https://common.cnblogs.com/images/copycode.gif)
![](https://common.cnblogs.com/images/copycode.gif)
using EF.Core;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Ef.Data
{
public class StudentMap:EntityTypeConfiguration<Student>
{
public StudentMap()
{
this.HasKey(s => s.ID);
this.Property(s => s.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
this.Property(s => s.Name).HasColumnType("nvarchar").HasMaxLength(50).IsRequired();
this.Property(s => s.Sex).HasColumnType("nvarchar").IsRequired();
this.Property(s => s.Age).IsRequired();
// this.Property(s => s.Email).IsRequired(); this.ToTable("Students");
}
}
}
![](https://common.cnblogs.com/images/copycode.gif)
![](https://common.cnblogs.com/images/copycode.gif)
using Ef.Data;
using EF.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace EF.App
{
public class Program
{ static void Main(string[] args)
{
Console.WriteLine("你好,请输入姓名:");
string name = Console.ReadLine().Trim();
Console.WriteLine("请输入年龄:");
int result = 0;
//转换成功,result是正确的结果
if (!int.TryParse(Console.ReadLine().Trim(), out result))
{
Console.WriteLine("请输入正确格式的年龄");
return;
}
Console.WriteLine("请输入你的性别:");
string sex = Console.ReadLine(); //Console.WriteLine("请输入你的Email:");
//string email = Console.ReadLine(); using(var db=new EFDbContext())
{
Student model = new Student()
{
Name = name,
Sex = sex,
Age = result,
// Email=email }; //db.Set<Student>().Add(model);或者下面的
db.Entry(model).State = System.Data.Entity.EntityState.Added;
db.SaveChanges(); }
Console.Write("Success!");
Console.ReadKey(); }
}
}
![](https://common.cnblogs.com/images/copycode.gif)
运行之后,还肯定会报错的,因为已经没有数据库迁移了:
我们做如下修改:
![](https://common.cnblogs.com/images/copycode.gif)
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Ef.Data
{
public class EFDbContext:DbContext
{
public EFDbContext()
: base("name=DbConnectionString")
{
//把数据库初始化策略设置为null
Database.SetInitializer<EFDbContext>(null);
} protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new StudentMap());
//base.OnModelCreating(modelBuilder);
}
}
}
![](https://common.cnblogs.com/images/copycode.gif)
然后运行项目,就不错报错了,这是不使用数据库迁移技术做到的。
看下数据库:
两种方式都可以,不过还是推荐官方的方式,数据库迁移技术。
EF中 Code-First 方式的数据库迁移的更多相关文章
- 2.EF中 Code-First 方式的数据库迁移
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...
- EF 中 Code First 的数据迁移以及创建视图
写在前面: EF 中 Code First 的数据迁移网上有很多资料,我这份并没什么特别.Code First 创建视图网上也有很多资料,但好像很麻烦,而且亲测好像是无效的方法(可能是我太笨,没搞成功 ...
- MVC中code first方式开发,数据库的生成与更新
在使用EF的实际编程中我们经常遇到这样的问题:发现实体结构需要新增加一个字段,或者减少一个字段,急需把实体结构修改,并让数据库更新这种修改.在用Model First或者Database First的 ...
- EF Code First教程-03 数据库迁移Migrator
要在nuget 程序包管理控制台中输入命令 基本命令 Enable-Migrations //打开数据库迁移 Add-Migration AddBlogUrl //新增一个数据库迁移版本 ...
- 【EF6学习笔记】(一)Code First 方式生成数据库及初始化数据库实际操作
本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习笔记参考原文中的流程,为了增加实际操作性,并能够深入理解,部分地方根据实际情况做了一些调整 ...
- EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作
EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本篇参考原文地址: Creating an Entity Framework Data Model 说明:学习 ...
- EF架构~codeFirst从初始化到数据库迁移
一些介绍 CodeFirst是EntityFrameworks的一种开发模式,即代码优先,它以业务代码为主,通过代码来生成数据库,并且加上migration的强大数据表比对功能来生成数据库版本,让程序 ...
- 【EF Code First】Migrations数据库迁移
1,打开工具->NuGet程序管理器->程序包管理器控制台 默认项目中要选择 数据访问上下文类 所在的项目 我的DB是在命名空间CodeFirst.UI下的所以选择CodeFirst. ...
- 【转】MVC中code first方式开发,数据库的生成与更新(Ef6)
一,在models文件夹中,建立相应的model文件 这里注意一点,这里建立的class名,就是数据库里表的名字. 在这里面,可以建立表之间的关系. 这里要说明一点的事 ...
随机推荐
- Leetcode 375.猜数字大小II
猜数字大小II 我们正在玩一个猜数游戏,游戏规则如下: 我从 1 到 n 之间选择一个数字,你来猜我选了哪个数字. 每次你猜错了,我都会告诉你,我选的数字比你的大了或者小了. 然而,当你猜了数字 x ...
- js的undefined怎么判断
window.undefined=window.undefined 如何理解呢?百度搜索:window.undefined=window.undefined 博客说是为了兼容老浏览器. 技巧: 调试时 ...
- nodemailer发送邮件遇到的一些问题
使用nodemailer发送邮件一直困惑了我好几天,百度谷歌都没有找到的几个问题,方便大家排查. 我使用的是0.7.1版本,其他的版本好像报错,就没用. 错误信息:Mail from command ...
- rabbitmq php扩展amqp安装
configure: error: Please reinstall the librabbitmq distribution itself or (re)install librabbitmq de ...
- shell的case-esac
case ... esac 与其他语言中的 switch ... case 语句类似,是一种多分枝选择结构. case 语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令.case语句格式如下: ...
- ZipKin原理学习--zipkin支持日志打印追踪信息
目前在zipkin brave已经提供功能在我们使用logback或log4j等时可以在日志信息中将traceId和spanId等信息打印到运行日志,这样可能对我们通过日志查看解决问题有比较大的 ...
- [BZOJ2393] Cirno的完美算数教室(dfs+容斥原理)
传送门 先通过dfs预处理出来所有只有2和9的数,也就大概2000多个. 想在[L,R]中找到是这些数的倍数的数,可以通过容斥原理 那么如果a % b == 0,那么便可以把 a 去掉,因为 b 的倍 ...
- POJ 2155 Matrix【二维线段树】
题目大意:给你一个全是0的N*N矩阵,每次有两种操作:1将矩阵中一个子矩阵置反,2.查询某个点是0还是1 思路:裸的二维线段树 #include<iostream>#include< ...
- [NOI2001] 食物链 (扩展域并查集)
题目描述 动物王国中有三类动物 A,B,C,这三类动物的食物链构成了有趣的环形.A 吃 B,B 吃 C,C 吃 A. 现有 N 个动物,以 1 - N 编号.每个动物都是 A,B,C 中的一种,但是我 ...
- spring mvc 单元测试示例
import java.awt.print.Printable; import java.io.IOException; import javax.servlet.http.HttpServletRe ...