AspMvc数据库上下⽂初始化器
在Asp Mvc 和Entity FrameWork程序中,如果数据库不存在,EF默认的⾏为是新建⼀个数据库。如果模型类与已有的数据库不匹配的时候,会抛出⼀个异常。
通过指定数据库上下⽂对象初始化器,可以执⾏删除和重新创建数据库,并⽤种⼦⽅法填充数据库。
当Asp Mvc 应⽤程序每⼀次运⾏的时候,Entity Framework 能够⾃动创建(或者删除重新创建)数据库。你能够指定每⼀次程序运⾏的时候,或者模型与已有数据库不匹配的时候执⾏删除重新创建操作,通过指定Seed ⽅法,EF能⾃动的调⽤Seed⽅法在你重新创建数据库后⾃动的填充数据。
注意:在数据迁移中执⾏种⼦⽅法后,会将种⼦⽅法中的数据记录还原成种⼦⽅法中的记录值,也就是说不能保存在U中I做的的更改。因为每次迁移后执⾏Update-Database命令更新数据后都要调⽤种⼦⽅法。
⽽采⽤初始化器的⽅式如果模型类没有变化,就不会执⾏初始化器中的种⼦⽅法,所以在UI中更改或删除记录的变化是保存的。
第⼀种场景:在开发阶段,模型类需要快速迭代,为了保持⽣成的数据库与模型类⼀致,需要删除重新创建数据库,但会导致丢失测试的数据,所以使⽤EF数据库初始化器并⽤种⼦⽅法⾃动填充测试数据,
以⽅便测试。
第⼀步:创建数据库初始化器。
1、创建DropCreateDatabaseAlways<DbContext>数据库初始化器。在程序每次运⾏的时候都执⾏删除、重新创建数据库操作
{
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>数据库初始化器。当模型发⽣更改的时候,执⾏删除、重新创建数据库操作
{
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>
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()
asp查看源码配置ui: base("MajorContext")
{ }
//静态构造函数。MSDN:静态构造函数⽤于初始化任何静态数据,或⽤于执⾏仅需执⾏⼀次的特定操作。在创建第⼀个实例或引⽤任何静态成员之前,将⾃动调⽤静态构造函数
static MajorContext()
{
//设置数据库初始化器,它就在应⽤程序运⾏的时候加载。
Database.SetInitializer<MajorContext>(new MajorContextInitializer());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)  // OnModelCreating ⽅法重写的⽬的是指定对应Dbse实体集的表格的名称应该是单数,如果没有此⽅法,数据库中的表格名称会按惯例为复数的名称,如 Studnets、Courses
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。