如果模型类(数据库上下文类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 迁移使用的更多相关文章

  1. 学习ASP.NET MVC(九)——“Code First Migrations ”工具使用示例

    在上一篇文章中,我们学习了如何使用实体框架的“Code First Migrations ”工具,使用其中的“迁移”功能对模型类进行一些修改,同时同步更新对应数据库的表结构. 在本文章中,我们将使用“ ...

  2. ASP.NET MVC中使用窗体验证出现上下文的模型在数据库创建后发生更改,导致调试失败(一)

    在ASP.NET MVC中使用窗体验证.(首先要明白,验证逻辑是应该加在Model.View和Controller哪一个里面?由于Model的责任就是负责信息访问与商业逻辑验证的,所以我们把验证逻辑加 ...

  3. 如何在 ASP.NET MVC 中集成 AngularJS(3)

    今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...

  4. 如何在 ASP.NET MVC 中集成 AngularJS(2)

    在如何在 ASP.NET MVC 中集成 AngularJS(1)中,我们介绍了 ASP.NET MVC 捆绑和压缩.应用程序版本自动刷新和工程构建等内容. 下面介绍如何在 ASP.NET MVC 中 ...

  5. asp.net mvc 中 一种简单的 URL 重写

    asp.net mvc 中 一种简单的 URL 重写 Intro 在项目中想增加一个公告的功能,但是又不想直接用默认带的那种路由,感觉好low逼,想弄成那种伪静态化的路由 (别问我为什么不直接静态化, ...

  6. Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)

    上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...

  7. 为Asp.net MVC中的RenderSection设置默认内容

    1. RenderSection的简单介绍 Asp.net MVC中提供了RenderSection方法,这样就能够在Layout中定义一些区块,这些区块留给使用Layout的view来实现比如我们定 ...

  8. IoC容器Autofac - Autofac + Asp.net MVC + EF Code First(转载)

    转载地址:http://www.cnblogs.com/JustRun1983/archive/2013/03/28/2981645.html  有修改 Autofac通过Controller默认构造 ...

  9. ASP.NET MVC中使用ASP.NET AJAX异步访问WebService

    使用过ASP.NET AJAX的朋友都知道,怎么通过ASP.NET AJAX在客户端访问WebService,其实在ASP.NET MVC中使用ASP.NET AJAX异步访问WebService 也 ...

随机推荐

  1. .NET 调用java webservice保存datetime类型数据为空的解决办法

    问题描述:       用C#.NET调用Java开发的WebService时,先在客户端封装的带有int属性的对象,当将该对象传到服务器端时,服务器端可以得到 string类型的属性值,却不能得到i ...

  2. 【HDOJ6298】Maximum Multiple(数论)

    题意:给定n,求x,y,z三个整数,使得x|n,y|n,z|n,且xyz最小 n<=1e6 思路: 不定方程1/x+1/y+1/z=1 只有(2,3,6)(2,4,4) (3,3,3)三组正整数 ...

  3. hdu 5195 DZY Loves Topological Sorting BestCoder Round #35 1002 [ 拓扑排序 + 优先队列 || 线段树 ]

    传送门 DZY Loves Topological Sorting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131 ...

  4. 显示倒计时的Button按钮

    package com.pingyijinren.helloworld.activity; import android.os.CountDownTimer; import android.suppo ...

  5. THUPC2017看题总结

    THUPC2017 看题总结 #2402. 「THUPC 2017」天天爱射击 / Shooting 果题. 求当前子弹能会使多少块木板损坏,发现因为木板会随着子弹数目的增加而更加容易损坏,故此询问具 ...

  6. 动态规划:HDU 1114 Piggy-Bank

    Problem Description Before ACM can do anything, a budget must be prepared and the necessary financia ...

  7. 洛谷——P3225 [HNOI2012]矿场搭建

    P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...

  8. CentOS 5 全功能服务器搭建

    转自: http://www.php-oa.com/2007/12/27/centos-www.html 转:主要做为历史记录,以后用.另外很少见这么好的编译的文章,其实我不推荐用编译安装.但这个文章 ...

  9. [Angular] Expose Angular Component Logic Using State Reducers

    A component author has no way of knowing which state changes a consumer will want to override, but s ...

  10. Win8系统如何在桌面行显示我的电脑

    1 桌面右击-个性化   2 更改桌面图标-然后可以在桌面上显示需要的东西