前面七篇基本把Code First学习了一下,不过code first中会出现一个问题,就是数据迁移的问题。
一、数据准备
还是在前面的demo上修改,这次使用Province和City类。
public class Province
{
[Key]
public string ProvinceId { get; set; } public string ProvinceName { get; set; } public virtual ICollection<City> Citys { get; set; }
}
}
public class City
{
public int CityId { get; set; } public string CityName { get; set; } public string ProId { get; set; } [ForeignKey("ProId")]//ProId一对要存在
public Province Province { get; set; } }
static void Main(string[] args)
{
City cityA = new City() { CityName = "驻马店" };
City cityB = new City() { CityName = "周口" };
Province province = new Province() {ProvinceId="", ProvinceName = "河南省", Citys = new List<City>() { cityA, cityB } };
using (var db = new EFCodeFirstDbContext())
{
db.Provinces.Add(province);
db.SaveChanges();
Console.WriteLine("Success");
}
Console.ReadKey();
}
上面的会在数据库映射如下面的数据表
二、数据迁移
1.增加属性
在City类中增加一个属性 Description,在创建City对象时增加Description,再次运行会报下面的错误。
通过下面图的步骤打开程序包管理器控制台.
在上面的控制台输入下面的code,这个在默认项目上要选择正确,会在项目上增加Migrations文件夹和Configuration.cs类。
Enable-Migrations -EnableAutomaticMigrations
namespace EFCodeFirstDataAccess.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<EFCodeFirstDataAccess.EFCodeFirstDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
ContextKey = "EFCodeFirstDataAccess.EFCodeFirstDbContext";
} protected override void Seed(EFCodeFirstDataAccess.EFCodeFirstDbContext context)
{
// This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
}
然后执行下面的code
Add-Migration InitialCreate
然后会生成一个201609061311422_InitialCreate.cs类。
namespace EFCodeFirstDataAccess.Migrations
{
using System;
using System.Data.Entity.Migrations; public partial class InitialCreate : DbMigration
{
public override void Up()
{
AddColumn("dbo.Cities", "Description", c => c.String());
} public override void Down()
{
DropColumn("dbo.Cities", "Description");
}
}
}
执行下面的code生成与上面一致的数据库
Update-Database -Verbose
此时再次运行上面的C#代码就不会再报错。而且数据库的结构也和C#的相对应了。
2.增加类
在数据库模型中添加User类,执行程序包管理器控制台语句,Migrations文件夹中新增类文件
Add-Migration AddUser
此时会在项目中增加201609061323573_AddUser.cs类。
namespace EFCodeFirstDataAccess.Migrations
{
using System;
using System.Data.Entity.Migrations; public partial class AddUser : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Users",
c => new
{
UserId = c.Int(nullable: false, identity: true),
Name = c.String(),
Age = c.Int(nullable: false),
})
.PrimaryKey(t => t.UserId); } public override void Down()
{
DropTable("dbo.Users");
}
}
}
再次执行下面的code
Update-Database -Verbose
此时再次运行C#项目会在数据库中映射出一个Users表
3.删除属性
这次删除User类中的Age属性。依次执行下面的两行
Add-Migration ModifyUser
上面的一行会生成一个201609061334085_ModifyUser.cs类。
namespace EFCodeFirstDataAccess.Migrations
{
using System;
using System.Data.Entity.Migrations; public partial class ModifyUser : DbMigration
{
public override void Up()
{
DropColumn("dbo.Users", "Age");
} public override void Down()
{
AddColumn("dbo.Users", "Age", c => c.Int(nullable: false));
}
}
}
然后更新到数据库
Update-Database -Verbose
4.版本回溯
在项目中可能会存在版本回溯的情况,code first也有对应的解决方案。
Update-Database –TargetMigration: AddUser
Update-Database -Verbose
如果你想回滚一切至空数据库,可以使用命令 Update-Database –TargetMigration: $InitialDatabase,此时要在Configuration.cs中设置AutomaticMigrationDataLossAllowed = true;
5.生成数据库版本之间的Sql脚本
执行程序包管理器控制台语句,生成数据库版本之间的Sql脚本。该操作仅为生成Sql语句,并未在数据库中进行执行。其中-TargetMigration在未指定的情况,默认为迁移到最新的版本。
Update-Database -Script -SourceMigration:InitialCreate -TargetMigration:ModifyUser