如果模型类(数据库上下文类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. bzoj5108 [CodePlus2017]可做题 位运算dp+离散

    [CodePlus2017]可做题 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 87  Solved: 63[Submit][Status][Dis ...

  2. bzoj5090组题 分数规划

    组题 Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 542  Solved: 114[Submit][Status][Discuss] Descript ...

  3. 【BZOJ2982】combination(Lucas定理)

    题意:求C(n,m) n,m<=200000000 思路:c(n,m)=c(n mod mo,m mod mo)*c(n div mo,m div mo) mod mo (n>=mo或m& ...

  4. spring mvc dispatcherServlet

    1. 在web.xml中配置servlet对相应的url请求进行处理 <servlet> <servlet-name>springDispatcher</servlet- ...

  5. poj2243+poj1915骑士问题

    2243是骑士问题,八个格子的,BFS,因为要最短路经,所以没有用A*,A*跑不出来,太慢了,因为要搜索到所有解啊!一直更新最优,而BFS,一层一层搜索,第一次得到的便是最短的了!300格子,标记的话 ...

  6. 2017多校Round7(hdu6120~hdu6132)

    补题进度:9/13 1001 待填坑 1002(数学推导) 题意 有一个按顺序的n个点的k叉树,问每个点子树个数的异或和是多少(n,k<=1e18) 分析 可以先求出最大的d,满足d以上都是满K ...

  7. <项目><day12>通讯录(自己做的)

    设计一个通讯录主页面 <!DOCTYPE html> <html> <head> <title>电话本首页</title> <meta ...

  8. CORS:Source.priciple implimentation in Spring

    Cors(Cross-origin Resource Sharing)一种跨域访问技术,基本思想是使用自定义的HTTP头部允许浏览器和服务器相互了解对方,从而决定响应成功与否. CORS与JSONP对 ...

  9. 【APUE】进程间通信之信号量

    信号量是一个计数器,用于多进程对共享数据对象的访问 为了获得共享资源,进程需要执行下列操作: 1)测试控制该资源的信号量 2)若此信号量为正,则进程可以使用该资源,进程将信号量减1,表示它使用了一个资 ...

  10. 项目中遇到的HQL查询问题

    问题描写叙述: 目的:想要查询出全部最新版本号的组件 说明:组件:版本号 =1:n关系 ,假设这个组件仅仅有一个版本号也要可以查出来. 项目中使用的是内存数据库,无法看到表结构,这里的样例仅仅用于模拟 ...