Asp.net MVC 中Code First 迁移使用
如果模型类(数据库上下文类Context和POCO类)发生改变,与数据库中的结构不一致,系统默认会抛出一个异常。可以考虑使用代码优先迁移。
代码优先迁移执行UpSert数据库操作,它在每一次更新数据库(Update-Database)后执行,添加数据库中没有的记录,更新数据库已有的记录,通过UI添加的记录保持不变。(模型更改后需要重新编译程序,并修改各视图和方法绑定的白名单,如果不是第一次迁移,还需要设置迁移文件交下configtion.cs文件中的seed方法增加或改变字段。)执行步骤如下:
1、启用迁移。在库程序包控制台输入Enable-Migrations,(如果多个上下文对象,需要指定完整的上下文类,包括所在的命名空间如Enable-Migrations -ContextTypeName MvcMovie.Models.MovieDBContext),自动创建一个Migration 迁移文件夹,并在下面创建一个Configurations.cs的文件。可以在里面设置种子方法。
protected override void Seed(MvcMovie.Models.MovieDBContext context)
{
List<Movie> movies =new List<Movie>
{
new Movie{ Title="封神榜",ReleaseDate=DateTime.Parse("2015-1-10"),Genre="神话",Price=50.6M,Rating="成人" },
new Movie{ Title="喜羊羊与灰太狼",ReleaseDate=DateTime.Parse("2008-5-1"),Genre="卡通",Price=30.2M,Rating="儿童" },
new Movie{ Title="何以笙箫默",ReleaseDate=DateTime.Parse("2014-11-5"),Genre="爱情",Price=102.5M,Rating="成人" },
new Movie{ Title="倚天屠龙记",ReleaseDate=DateTime.Parse("2010-7-1"),Genre="武侠",Price=70.05M,Rating="成人" },
new Movie{ Title="天龙八部",ReleaseDate=DateTime.Parse("1998-8-8"),Genre="武侠",Price=200.2M,Rating="成人" },
new Movie{ Title="全面回忆",ReleaseDate=DateTime.Parse("2012-6-10"),Genre="科幻",Price=80.3M,Rating="成人" },
new Movie{ Title="黑衣人",ReleaseDate=DateTime.Parse("2014-6-12"),Genre="科幻",Price=150.3M,Rating="成人" },
new Movie{ Title="熊出没",ReleaseDate=DateTime.Parse("2013-8-13"),Genre="卡通",Price=40.6M,Rating="儿童" },
new Movie{ Title="西游记",ReleaseDate=DateTime.Parse("1984-5-21"),Genre="神话",Price=110.05M,Rating="成人" },
};
movies.ForEach(m => context.Movies.AddOrUpdate(s => s.Title, m));
//或者 context.Movies.AddOrUpdate(m => m.Title, movies.ToArray());
context.SaveChanges();
}
2、创建迁移。在库程序包控制台输入 Add-Migration Rating。程序将比对模型类(数据库上下文类Context和POCO类)与数据库的一致性,将创建一个时间戳+迁移名字的cs文件,里面包含有根据模型类创建更改数据库的UP方法。可以在执行UpDate-Database 前创建多个迁移,然后它们能按照顺序依次执行,是因为在每个迁移文件前有一个时间戳。
同时
3、升级数据库。编译程序,在库程序包控制台输入 Update-Database 。第一个任务是将运行当前的迁移文件中的代码对数据库更改UP方法,第二是报告迁移配置文件中的Seed方法upsert数据,通过UI更改的数据如与Seed方法中的数据不一致,将还原成种子方法的数据。通过UI新增的数据能保存。
4、如果没有对模型作任何更改,运行update-database,就不会执行迁移,但会再次运行Seed方法,如果在UI界面中修改了Seed方法中的记录,数据库中的记录将还原成种子方法的记录值。
二、如果一个项目中有多个上下文类,在创建迁移的时候需要指定详细的上下文类或者指定可选的迁移文件夹目录,以防冲突。如果一个项目中有多个迁移,增加迁移和升级数据库时同样需要指定详细的迁移配置文件。
比如:1、一个项目中有多个上下文类,启用迁移
Enable-Migrations -ContextTypeName SimpleSite.Models.ApplicationDbContext -MigrationsDirectory Migrations\Identity
2、增加迁移:Add-Migration CssTheme -ConfigurationTypeName SimpleSite.Migrations.Identity.Configuration
3、升级数据库:Update-Database -ConfigurationTypeName SimpleSite.Migrations.Identity.Configuration 示例:
启用迁移: Enable-Migrations -ContextTypeName MajorConstruction.Models.MajorContext 如果不指定-MigrationsDirectory 默认是迁移文件是在项目的Migrations 文件夹下面。
增加迁移:Add-Migration ArticleIsShow -ConfigurationTypeName MajorConstruction.Migrations.Configuration
升级数据库:Update-Database -ConfigurationTypeName MajorConstruction.Migrations.Configuration
如果迁移是增加或修改必填写字段,如Boolean值。则可以修改有时间戳的迁移文件中指定默认值,因为执行升级数据库命令后,先是运行迁移文件中的UP方法,再运行Configuration配置文件下的 Seed种子方法。
如:
public partial class ArticleIsShow : DbMigration
{
public override void Up()
{
AddColumn("dbo.Article", "ArticleIsShow", c => c.Boolean(nullable: false,defaultValue:true));
}
public override void Down()
{
DropColumn("dbo.Article", "ArticleIsShow");
}
}
}
三、可以在数据库上下文类中,为数据库上下文中指定连接字符串,多个上下文可以指定同一个连接字符串(但他们拥有不同的Dbset,也就是不同的实体集也就是对应的表),这样,就可以访问同一个数据库。同时,还可以在配置文件中,修改约定。
public class SiteDataContext:DbContext
{
public SiteDataContext() : base("DefaultConnection") { } //调用基类的构造函数。
public DbSet<Notification> Notifications { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
当对数据库中已有数据的情况下执行迁移,需要插入存根数据来满足表格的外键约束,比如有表格新增了一列不能为空的外键。可以在UP方法中建立一个临时的值记录作为默认的值满足外键约束,在up方法中,所有的记录都设置为这个默认值,然后种子方法会将有些记录设置成正确的值。
比如 原来的Course 实体没有DepartmentID 这个属性,而本次迁移执行前,数据库中已经有了记录了。
就需要在迁移文件中为DepartmentID 指定默认值.
// Create a department for course to point to.
Sql("INSERT INTO dbo.Department (Name, Budget, StartDate) VALUES ('Temp', 0.00, GETDATE())");
// default value for FK points to department created above.
AddColumn("dbo.Course", "DepartmentID", c => c.Int(nullable: false, defaultValue: 1));
//AddColumn("dbo.Course", "DepartmentID", c => c.Int(nullable: false));
对于多对多关系,EF Code First 会自动创建关联的 各主键约束表格,但可以通过Fluent API配置表格的列名和表名。
modelBuilder.Entity<Course>()
.HasMany(c => c.Instructors).WithMany(i => i.Courses)
.Map(t => t.MapLeftKey("CourseID")
.MapRightKey("InstructorID")
Asp.net MVC 中Code First 迁移使用的更多相关文章
- 学习ASP.NET MVC(九)——“Code First Migrations ”工具使用示例
在上一篇文章中,我们学习了如何使用实体框架的“Code First Migrations ”工具,使用其中的“迁移”功能对模型类进行一些修改,同时同步更新对应数据库的表结构. 在本文章中,我们将使用“ ...
- ASP.NET MVC中使用窗体验证出现上下文的模型在数据库创建后发生更改,导致调试失败(一)
在ASP.NET MVC中使用窗体验证.(首先要明白,验证逻辑是应该加在Model.View和Controller哪一个里面?由于Model的责任就是负责信息访问与商业逻辑验证的,所以我们把验证逻辑加 ...
- 如何在 ASP.NET MVC 中集成 AngularJS(3)
今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...
- 如何在 ASP.NET MVC 中集成 AngularJS(2)
在如何在 ASP.NET MVC 中集成 AngularJS(1)中,我们介绍了 ASP.NET MVC 捆绑和压缩.应用程序版本自动刷新和工程构建等内容. 下面介绍如何在 ASP.NET MVC 中 ...
- asp.net mvc 中 一种简单的 URL 重写
asp.net mvc 中 一种简单的 URL 重写 Intro 在项目中想增加一个公告的功能,但是又不想直接用默认带的那种路由,感觉好low逼,想弄成那种伪静态化的路由 (别问我为什么不直接静态化, ...
- Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)
上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...
- 为Asp.net MVC中的RenderSection设置默认内容
1. RenderSection的简单介绍 Asp.net MVC中提供了RenderSection方法,这样就能够在Layout中定义一些区块,这些区块留给使用Layout的view来实现比如我们定 ...
- IoC容器Autofac - Autofac + Asp.net MVC + EF Code First(转载)
转载地址:http://www.cnblogs.com/JustRun1983/archive/2013/03/28/2981645.html 有修改 Autofac通过Controller默认构造 ...
- ASP.NET MVC中使用ASP.NET AJAX异步访问WebService
使用过ASP.NET AJAX的朋友都知道,怎么通过ASP.NET AJAX在客户端访问WebService,其实在ASP.NET MVC中使用ASP.NET AJAX异步访问WebService 也 ...
随机推荐
- php之ThinkPHP的memcached类的修改
php之ThinkPHP的memcached类的修改 在Think\Cache\Driver\Memcached.class.php中,增加方法获取错误信息的方法,方便调试, public funct ...
- spring boot 没有主清单属性
- 无向图生成树计数 基尔霍夫矩阵 SPOJ Highways
基尔霍夫矩阵 https://blog.csdn.net/w4149/article/details/77387045 https://blog.csdn.net/qq_29963431/articl ...
- BUPT2017 springtraining(16) #1 题解
https://vjudge.net/contest/162590 A: 不难发现,当L=R时输出L,当L<R时输出2. B: 贪心得配对.1和n配 2和n-1配,对与对直接只要花1个代价就可以 ...
- Spring Boot修改Thymeleaf版本(从Thymeleaf2.0到3.0)
Spring Boot默认选择的Thymeleaf是2.0版本的,那么如果我们就想要使用3.0版本或者说指定版本呢,那么怎么操作呢?在这里要说明下 3.0的配置在spring boot 1.4.0+才 ...
- MatConvNet 练习使用CNN
首先在 VGG Convolutional Neural Networks Practical 官网上做了四个练习.现在代码可以直接用 但是在using pretrained models中有个错,n ...
- poj 1695 Magazine Delivery 记忆化搜索
dp[a][b][c],表示三个人从小到大依次在a,b.c位置时.距离结束最少的时间. 每次选一个人走到c+1位置搜索就好了. 坑点在于不能floyd.预计题目没说清楚.意思就是假设没送Li,那么Li ...
- jni——如何转换有符号与无符号数
java数据结构默认均为有符号数,而通过jni转换到c/c++层,却不一定是有符号数. 如若在java中存储的即为无符号数,则在jni中可将jbyte直接进行类型转换. 若进行操作,则可在计算时,先将 ...
- android KE or NE分析
使用arm-eabi-addr2line工具跟踪Android调用堆栈 在通常的C/C++代码中,可以通过响应对内存操作不当引起的Segmentation Fault错误即信号SIGSEGV(11)做 ...
- Linux-github 搭建静态博客
1.在Github上创建一个新的Repository 到你的github上 https://github.com去create a new repository命名为 github.myblog 2. ...