前面的文章中,学习了 EF 中的几种关系,一对一,一对多,多对多。但是相信大家肯定会有疑问:
1. 我难道每次都要创建数据库么?
2. 我怎么样从已经存在的表中,添加字段和移除字段呢?
3. 当我向表中,添加字段或者移除字段,我怎么来避免丢失数据呢?
4. 当数据库发生改变的时候,我怎么获取到创建数据库的脚本呢?
不用着急,这篇文章,我会向大家一一讲到:
首先,说说我们为什么要使用数据库迁移技术吧,因为我们的实体总是变动地很频繁,在上篇文章中,我们使用了数据库初始化策略来做,也就是每次当数据库不存在的时候,就创建数据库【类似还有几种初始化策略】,然而,当你的实体改变的时候,在使用这个策略,EF 就会报错。而数据库迁移技术就可以帮到我们,我们不用每次都创建数据库。并且数据库迁移技术还可以为我们设置初始化的数据。
先看看项目结构吧:
我们需要建 2 个类库项目,还有一个控制台的程序:
Student 类:
- 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;
- }
- }
- }
StudentMap 类:
- 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 {
- 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");
- }
- }
- }
EF 上下文类:
- 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);
- }
- }
- }
数据库连接字符串:【在 EF.Data 的配置文件和控制台的项目的配置文件中都要写:】另外注意:这两个项目需要引入 EF
- "DbConnectionString"connectionString = "Server=.;database=StudentEFDB;uid=sa;pwd=Password_1"providerName = "System.Data.SqlClient" / >
控制台中:
- 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();
- }
- }
- }
运行之后,写入数据。
看下数据库中的数据:
好了,这就完成了第一阶段的准备工作:现在我们需要在 Student 实体中加一个字段 Email,项目做一下变动:
- 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;
- }
- }
- }
- 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 {
- 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");
- }
- }
- }
- 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();
- }
- }
- }
运行之后:报错,很正常嘛,这肯定报错,因为我们的实体改了。。
怎么办呢??别着急,我们来启用数据库迁移技术:
在程序包控制台中输入:
Enable-Migrations
接着按回车键,在项目中就会生成 Migration 文件夹,自己去看看里面有啥东东吧。
然后打开 Configuration 类:修改一下代码:
接着在程序包管理器控制台中输入:
Update-Database -Verbose
好了,现在运行一下项目吧:
看到了么,到这里就没报错了。运行完之后,我们看下数据库中的数据:
可以看到之前的数据也在,也就是数据没有丢失。是不是很神奇呢???
总结:这两篇文章总结了 EF 的一些使用,希望你喜欢。
题外篇:这里是使用 EF 中的数据库迁移技术。我们就可以随时随地的添加删除字段。而不用手动去删除数据库,那样会丢失数据。
现在,我就想不用数据库迁移呢?
我删掉之前生成的 Migration 文件夹【包括里面的类】,然后修改代码【删除刚才添加的 Email 字段】:
- 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; }
- }
- }
- 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 {
- 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");
- }
- }
- }
- 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();
- }
- }
- }
运行之后,还肯定会报错的,因为已经没有数据库迁移了:
我们做如下修改:
- 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);
- }
- }
- }
然后运行项目,就不错报错了,这是不使用数据库迁移技术做到的。
看下数据库:
两种方式都可以,不过还是推荐官方的方式,数据库迁移技术。
来源: http://www.cnblogs.com/caofangsheng/p/5798324.html