在Asp.net Mvc 和Entity FrameWork程序中,如果数据库不存在,EF默认的行为是新建一个数据库。如果模型类与已有的数据库不匹配的时候,会抛出一个异常。

通过指定数据库上下文对象初始化器,可以执行删除和重新创建数据库,并用种子方法填充数据库。

当Asp.net Mvc 应用程序每一次运行的时候,Entity Framework 能够自动创建(或者删除重新创建)数据库。你能够指定每一次程序运行的时候,或者模型与已有数据库不匹配的时候执行 删除重新创建操作,通过指定Seed 方法,EF能自动的调用Seed方法在你重新创建数据库后自动的填充数据。

注意:在数据迁移中执行种子方法后,会将种子方法中的数据记录还原成种子方法中的记录值,也就是说不能保存在U中I做的的更改。因为每次迁移后执行Update-Database命令更新数据后都要调用种子方法。

而采用初始化器的方式如果模型类没有变化,就不会执行初始化器中的种子方法,所以在UI中更改或删除记录的变化 是保存的。

第一种场景:在开发阶段,模型类需要快速迭代,为了保持生成的数据库与模型类一致,需要删除重新创建数据库,但会导致丢失测试的数据,所以使用EF数据库初始化器并用种子方法自动填充测试数据,以方便测试。

第一步:创建数据库初始化器。

1、创建DropCreateDatabaseAlways<DbContext>数据库初始化器。在 程序每次运行的时候都执行删除、重新创建数据库操作

public class SchoolInitializer:DropCreateDatabaseAlways<SchoolContext>
{

protected override void Seed(SchoolContext context)
{
var students = new List<Student>
{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};

students.ForEach(s => context.Students.Add(s));
context.SaveChanges();

2、创建DropCreateDatabaseIfModelChanges<DbContext>数据库初始化器。当模型发生更改的时候,执行删除、重新创建数据库操作

public class SchoolInitializer:DropCreateDatabaseIfModelChanges<SchoolContext>
{
protected override void Seed(SchoolContext context)
{
var students = new List<Student>
{
new Student {FirstMidName ="张",LastName="三",EnrollmentDate=DateTime.Parse("1979-9-1")}
new Student {FirstMidName ="李",LastName="四",EnrollmentDate=DateTime.Parse("2000-9-1")},
new Student {FirstMidName ="王",LastName="二",EnrollmentDate=DateTime.Parse("1979-9-1")}
new Student {FirstMidName ="陈",LastName="五",EnrollmentDate=DateTime.Parse("2000-9-1")},
};

students.ForEach(s => context.Students.Add(s));
context.SaveChanges();

第2步:在应用程序中指定数据库初始化器。有两种方法

1、在Asp.Net Mvc 应用程序 根目录的 Web.Config 的XML文件中的<EntityFramework>节点中配置

<entityFramework>
<contexts>
<context type="ContosoUniversity.DAL.SchoolContext, ContosoUniversity">
<databaseInitializer type="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity" /> //disableDatabaseInitialization="true".可以关闭初始化器
</context>
</contexts>

2、在全局应用程序配置文件Global.asax 中的 Application_Start 方法中通过代码的方式指定。

Database.SetInitializer<SchoolContext>(new SchoolInitializer());

第二种场景:部署阶段 如果需要在部署的产品中存储初始化数据,比如在角色权限系统中的超级管理员用户名、密码信息,以便能够登录,或执行其他一些初始化操作,也需要定义和使用一个 数据库上下文初始化器,只能使用 DropCreateDatabaseIfModelChanges<SchoolContext>

第一步:定义一个数据库初始化器

public class MajorContextInitializer:DropCreateDatabaseIfModelChanges<MajorContext>
{
protected override void Seed(MajorContext context)
{
var themeList = new List<BootstrapTheme>()
{
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Stock" ,ThemeDescription="默认主题。黑色背景导航条,蓝色背景标题", IsActived=true},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Cerulean" ,ThemeDescription="深蓝色背景导航条,浅蓝色背景标题", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Cosmo" ,ThemeDescription="天蓝色背景导航条,天蓝色背景标题", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Darkly" ,ThemeDescription="翠绿色背景导航条,蓝黑色背景标题,黑色背景", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Flatly" ,ThemeDescription="翠绿色背景导航条,蓝黑色背景标题", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Sandstone" ,ThemeDescription="绿色背景导航条,蓝黑色背景标题", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Spacelab" ,ThemeDescription="深蓝色背景导航条,深蓝色背景标题", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Superhero" ,ThemeDescription="橘黄色背景导航条,橘黄色背景标题,小号字", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="United" ,ThemeDescription="朱红色背景导航条,橘黄色背景标题", IsActived=false},
new BootstrapTheme { BootstrapThemeID=Guid.NewGuid().ToString(), ThemeName="Yeti" ,ThemeDescription="蓝色背景导航条,蓝色背景标题,小号字", IsActived=false}
};

//这里如果不使用Foreach 语句遍历,也可以使用 themeList.Foreach(s =>context.BootstrapThemes.AddOrUpdate(p =>p.ThemeName,s)) 执行upsert操作,以themeName 主题名称作为区分不同的主题。
foreach (var theme in themeList)
{
var _theme = context.BootstrapThemes.Where(x => x.ThemeName == theme.ThemeName).FirstOrDefault();
if (_theme == null)
{
context.BootstrapThemes.Add(theme);

}

}
context.SaveChanges(); //这里实际上并需要使用context.SaveChages().主要是方便调试,定位错误出在哪里。

//既然使用静态构造函数可以初始化主题,那么也应该可以初始化其它DbSet 实体集成员。
var categoryList = new List<Category>()
{
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="专业动态",CategoryDescription="专业建设进展情况",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=1},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="运行机制",CategoryDescription="制度建设情况",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=2},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="教学队伍",CategoryDescription="专业带头人、师资队伍、团队建设情况",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=3},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="实践条件",CategoryDescription="校内、校外实训基地建设",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=4},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="培养方案",CategoryDescription="人才培养方案",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=5},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="校企合作",CategoryDescription="校企合作情况",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=6},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="社会服务",CategoryDescription="社会服务情况",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=7},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="政策法规",CategoryDescription="高等职业教育制度",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=8},
new Category{ CategoryID=Guid.NewGuid().ToString(), CategoryName="课程体系",CategoryDescription="课程体系构成",NavbarIsShow=true,IndexPageIsShow=true, PriorOrder=9}
};

foreach(var category in categoryList)
{
var _category = context.Categories.Where(x => x.CategoryName == category.CategoryName).FirstOrDefault();
if (_category == null)
{
context.Categories.Add(category);
}

}

context.SaveChanges(); //这里实际上并需要使用context.SaveChages().主要是方便调试,定位错误出在哪里。

//添加一条默认的专业名称记录;
var majorName = new MajorName { MajorNameID = Guid.NewGuid().ToString(), MajorNameText = "数控技术" };
if(context.MajorNames.Count() ==0)
{
context.MajorNames.Add(majorName);

}
context.SaveChanges(); //这里实际上并需要使用context.SaveChages().主要是方便调试,定位错误出在哪里。

base.Seed(context);
}
}

第二步:在数据库上下文对象中中定义一个数据库静态构造函数,在静态构造函数中设定初始化器。则每一次调用数据库上下文对象的时候都要检查数据库中是否存在这些初始值,会降低程序的响应速度。 这种方法不是最佳实践。网站性能并不如在应用程序启动的时候才执行初始化(可在global.asx或在webconfig 中指定DatabaseInitializer指定初始化器)。

public class MajorContext:DbContext
{
public DbSet<Category> Categories { get; set; }

public DbSet<Article> Articles { get; set; }

public DbSet<Course> Courses { get; set; }

public DbSet<Resource> Resources { get; set; }

public DbSet<BootstrapTheme> BootstrapThemes { get; set; }

public DbSet<MajorName> MajorNames { get; set; }

public MajorContext()
: base("MajorContext")
{ }

//静态构造函数。MSDN:静态构造函数用于初始化任何静态数据,或用于执行仅需执行一次的特定操作。在创建第一个实例或引用任何静态成员之前,将自动调用静态构造函数
static MajorContext()
{
//设置数据库初始化器,它就在应用程序运行的时候加载。
Database.SetInitializer<MajorContext>(new MajorContextInitializer());
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)  // OnModelCreating 方法重写的目的是指定对应Dbse实体集的表格的名称应该是单数,如果没有此方法,数据库中的表格名称会按惯例为复数的名称,如 Studnets、Courses
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}

}

Asp.net Mvc 数据库上下文初始化器的更多相关文章

  1. ASP.NET Core 数据库上下文 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 数据库上下文 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 数据库上下文 上一章节中我们了解了 Entity Framewo ...

  2. ASP.NET MVC 数据库依赖缓存

    ASP.NET MVC 数据库依赖缓存   问题背景 最近做一个非常简单的功能,就是使用ajax请求的方式从服务端请求一段下拉表的数据. 以前也有做过这个功能,只不过这次做这个功能的时候冒出了一个想法 ...

  3. ASP.NET MVC 异常Exception拦截器Fillter

    异常信息的处理在程序中非常重要, 在asp.net mvc中提供异常属性拦截器进行对异常信息的处理,异常拦截器也没有什么的,只是写一个类,继承另一个类(System.Web.Mvc.FilterAtt ...

  4. ASP.NET MVC 数据库依赖缓存的实现

    当数据库中的信息发生变化的时候,应用程序能够获取变化的通知是缓存依赖得以实现的基础.应用程序可以通过轮询获取数据变化的信息,使用轮询的话也不可能重新查一次后再和以前的数据做比较,如果这样的话如果我一个 ...

  5. ASP.NET MVC中的拦截器

    在ASP.NET MVC中,有三种拦截器:Action拦截器.Result拦截器和Exception拦截器, 所谓的拦截器也没有什么的,只是写一个类,继承另一个类和一个接口,顺便实现接口里面的方法而以 ...

  6. 初遇 Asp.net MVC 数据库依赖缓存那些事儿

    问题背景: 最近做一个非常简单的功能,就是使用ajax请求的方式从服务端请求一段下拉表的数据. 以前也有做过这个功能,只不过这次做这个功能的时候冒出了一个想法: 我请求的这段数据它是一段相对比较固定的 ...

  7. ASP.NET MVC数据库初始化

    public class DBInitializer:DropCreateDatabaseAlways<BookDBContext> { protected override void S ...

  8. ASP.NET MVC的Action拦截器(过滤器)ActionFilter

    有时项目要进行客户端请求(action)进行拦截(过滤)验证等业务,可以使用拦截器进行实现,所谓的action拦截器也没有什么的,只是写一个类,继承另一个类(System.Web.Mvc.Filter ...

  9. 模型(Model)– ASP.NET MVC 4 系列

           为 MVC Music Store 建模        在 Models 目录中为专辑.艺术家.流派建模: public class Album { public virtual int ...

随机推荐

  1. 关于HTML文件、JS文件、CSS文件

    把JS和CSS脚本写在html里和写在独立文件里有什么区别? 1. 都写在html里是性能最优的方案. 2. 都写在html里是可维护性最差的方案. 3. 分开写在js.css.html是可维护性最有 ...

  2. Segments--poj3304(判断直线与线段之间的关系)

    http://poj.org/problem?id=3304 给你几条线段  然后 让你找到一条直线让他在这条直线上的映射有一个重合点 如果有这条直线的话  这个重合的部分的两个端点一定是某两条线段的 ...

  3. Sudoku---hdu2676(数独DFS)

    http://poj.org/problem?id=2676 递归深搜 #include<stdio.h> #include<string.h> #include<alg ...

  4. Linux--进程组、会话、守护进程(转)

    http://www.cnblogs.com/forstudy/archive/2012/04/03/2427683.html 进程组 一个或多个进程的集合 进程组ID: 正整数 两个函数 getpg ...

  5. Java的vector可实现自动增长的数组

    Vector维克多提供了向量类(vector)以实现类似动态数组的功能. 首先,在Java中并没有指针这样的概念 ,但如果正确灵活地使用指针又确实可以大大提高程序的质量.比如在c,c++中所谓的“动态 ...

  6. Spring基础入门(二)

    一.AOP 1.AOP概念 aop:面向切面编程,扩展功能不修改源代码实现. AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码. 2.AOP原理 (1)第一种情况,有接口情况,使用动态代理创建 ...

  7. (转)Redis

    Rdis和JQuery一样是纯粹为应用而产生的,这里记录的是在CentOS 5.7上学习入门文章: 1.Redis简介 Redis是 一个key-value存储系统.和Memcached类似,但是解决 ...

  8. 基于commons-net实现ftp创建文件夹、上传、下载功能

    原文:http://www.open-open.com/code/view/1420774470187 package com.demo.ftp; import java.io.FileInputSt ...

  9. system表空间用满解决

      分类: Oracle 早上看到alert日志报说system表空间快满了(oracle版本是11gR2):   如果system表空间不是自动扩展,空间用满甚至会出现数据库无法登陆.使用任何用户登 ...

  10. jmeter的线程组执行顺序不以其出现的顺序发生变化

    jmeter可以同时配置多个线程组,那么他们的执行顺序是什么呢?和他们出现的顺序有什么关系呢? 先说下几个特殊的线程组:tearDown线程组和setUp线程组,tearDown线程组一定在最后执行, ...