你的位置:首页 > ASP.net教程

[ASP.net教程]2. Code First Migrations With Entity Framework【EF中 Code


 前面的文章中,学习了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<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");    }  }}

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

<connectionStrings>  <add name="DbConnectionString" connectionString="Server=.;database=StudentEFDB;uid=sa;pwd=Password_1" providerName="System.Data.SqlClient" /> </connectionStrings>

控制台中:

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

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

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

 

 然后运行项目,就不错报错了,这是不使用数据库迁移技术做到的。

 

 看下数据库:

两种方式都可以,不过还是推荐官方的方式,数据库迁移技术。