Asp.net Mvc 数据库上下文初始化器
在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 数据库上下文初始化器的更多相关文章
- ASP.NET Core 数据库上下文 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 数据库上下文 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 数据库上下文 上一章节中我们了解了 Entity Framewo ...
- ASP.NET MVC 数据库依赖缓存
ASP.NET MVC 数据库依赖缓存 问题背景 最近做一个非常简单的功能,就是使用ajax请求的方式从服务端请求一段下拉表的数据. 以前也有做过这个功能,只不过这次做这个功能的时候冒出了一个想法 ...
- ASP.NET MVC 异常Exception拦截器Fillter
异常信息的处理在程序中非常重要, 在asp.net mvc中提供异常属性拦截器进行对异常信息的处理,异常拦截器也没有什么的,只是写一个类,继承另一个类(System.Web.Mvc.FilterAtt ...
- ASP.NET MVC 数据库依赖缓存的实现
当数据库中的信息发生变化的时候,应用程序能够获取变化的通知是缓存依赖得以实现的基础.应用程序可以通过轮询获取数据变化的信息,使用轮询的话也不可能重新查一次后再和以前的数据做比较,如果这样的话如果我一个 ...
- ASP.NET MVC中的拦截器
在ASP.NET MVC中,有三种拦截器:Action拦截器.Result拦截器和Exception拦截器, 所谓的拦截器也没有什么的,只是写一个类,继承另一个类和一个接口,顺便实现接口里面的方法而以 ...
- 初遇 Asp.net MVC 数据库依赖缓存那些事儿
问题背景: 最近做一个非常简单的功能,就是使用ajax请求的方式从服务端请求一段下拉表的数据. 以前也有做过这个功能,只不过这次做这个功能的时候冒出了一个想法: 我请求的这段数据它是一段相对比较固定的 ...
- ASP.NET MVC数据库初始化
public class DBInitializer:DropCreateDatabaseAlways<BookDBContext> { protected override void S ...
- ASP.NET MVC的Action拦截器(过滤器)ActionFilter
有时项目要进行客户端请求(action)进行拦截(过滤)验证等业务,可以使用拦截器进行实现,所谓的action拦截器也没有什么的,只是写一个类,继承另一个类(System.Web.Mvc.Filter ...
- 模型(Model)– ASP.NET MVC 4 系列
为 MVC Music Store 建模 在 Models 目录中为专辑.艺术家.流派建模: public class Album { public virtual int ...
随机推荐
- windows7 下安装使用memcached(二)
Memcached 安装使用 本地环境:Windows7 64位web环境:wamp集成环境,php版本:PHP Version 7.1.17 学习参考网站: RUNOOB.COM官网 http:/ ...
- [Noip复习知识点][个人向]Zackzh
只是列列一些要复习的,努力复习吧,有种noip退役的赶脚. 一.模拟 (这你也不会?退役吧) 二.DP 1.基础dp 2.区间dp 3.状压dp 4.树形dp 6.概率(期望)dp 7.环形dp 8. ...
- 过滤器链chain.doFilter(request,response)含义
过滤器的生命周期一般都要经过下面三个阶段: 初始化 当容器第一次加载该过滤器时,init() 方法将被调用.该类在这个方法中包含了一个指向 Filter Config 对象的引用. 过滤 过滤器的大多 ...
- IntelliJ 中类似于Eclipse ctrl+o的是ctrl+F12
IntelliJ 中类似于Eclipse ctrl+o的是ctrl+F12 学习了:https://blog.csdn.net/sjzylc/article/details/47979815
- 运维平台之CMDB系统建设
CMDB是运维的基础核心系统,所有的元数据和共享数据管理源,类似于业务中的账号平台的作用.本篇文章,我将从概念篇.模型篇.到实现与实施篇具体的进行阐述. CMDB也称配置管理,配置管理一直被认为是 I ...
- soapUI系列之—-02 Groovy脚本常用方法
------Groovy脚本常用方法 1. 设置参数值:setPropertyValuea. 设置 project level property//set to project level prope ...
- hadoop生态系统学习之路(十)MR将结果输出到hbase
之前讲了MR将结果输出到hdfs.hive.db,今天再给大家分享一下,怎样将结果输出到hbase. 首先,提一句,笔者在hadoop集群运行此MR的时候报了一个错误.是一个jar包的缘故,这个错误是 ...
- iOS开发--常用技巧 (MJRefresh详解)
iOS开发--常用技巧 (MJRefresh详解) https://github.com/CoderMJLee/MJRefresh 下拉刷新01-默认 self.tableView.head ...
- react-grid-layout
一个好用的拖拽.自适应布局 react 插件 基本使用: // 显示全部 chart 内容区域 import React,{PureComponent} from 'react'; import {R ...
- 【iOS系列】-程序开启后台运行
[iOS系列]-程序开启后台运行 iOS程序是伪后台的运行,可是有时候我们需要让其在后台也要进行一些操作,我们可以让其伪装成音乐的APP,这样就可以让程序后台进行相关操作了,具体做法如下: 1:在Ap ...