官方说法是:设定数据库种子https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/razor-pages/sql
应用背景:初次部署系统时,设定一些默认的数据,比如后台管理员初始账号等信息。
在 Models 文件夹中创建一个名为 SeedData
的新类。 将生成的代码替换为以下代码:
using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System; using System.Linq; namespace RazorPagesMovie.Models { public static class SeedData { public static void Initialize(IServiceProvider serviceProvider) { using (var context = new MovieContext( serviceProvider.GetRequiredService<DbContextOptions<MovieContext>>())) { // Look for any movies. if (context.Movie.Any()) { return; // DB has been seeded } context.Movie.AddRange( new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-2-12"), Genre = "Romantic Comedy", Price = 7.99M }, new Movie { Title = "Ghostbusters", ReleaseDate = DateTime.Parse("1984-3-13"), Genre = "Comedy", Price = 8.99M }, new Movie { Title = "Ghostbusters 2", ReleaseDate = DateTime.Parse("1986-2-23"), Genre = "Comedy", Price = 9.99M }, new Movie { Title = "Rio Bravo", ReleaseDate = DateTime.Parse("1959-4-15"), Genre = "Western", Price = 3.99M } ); context.SaveChanges(); } } } }
如果 DB 中没有任何电影,则会返回种子初始值设定项,并且不会添加任何电影。(不是很理解该翻译,个人理解是:如果数据表中存在记录,则返回,不会将初始化数据写入数据表中。)
if (context.Movie.Any()) { return; // DB has been seeded. }
添加种子初始值设定项
将种子初始值设定项添加 Program.cs 文件中的 Main
方法末端:
// Unused usings removed. using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using RazorPagesMovie.Models; using System; using Microsoft.EntityFrameworkCore; namespace RazorPagesMovie { public class Program { public static void Main(string[] args) { var host = BuildWebHost(args);//初始化数据库开始 using (var scope = host.Services.CreateScope()) { var services = scope.ServiceProvider; try { var context = services.GetRequiredService<MovieContext>(); // requires using Microsoft.EntityFrameworkCore; context.Database.Migrate(); // Requires using RazorPagesMovie.Models; SeedData.Initialize(services); } catch (Exception ex) { var logger = services.GetRequiredService<ILogger<Program>>(); logger.LogError(ex, "An error occurred seeding the DB.初始化数据库时发生错误!"); } }//初始化数据库结束 host.Run(); } public static IWebHost BuildWebHost(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .Build(); } }
测试应用
- 删除 DB 中的所有记录。 可以使用浏览器中的删除链接,也可以从 SSOX 执行此操作
-
强制应用初始化(调用
Startup
类中的方法),使种子方法能够正常运行。 若要强制进行初始化,必须先停止 IIS Express,然后再重新启动它。 可以使用以下任一方法来执行此操作:-
右键单击通知区域中的 IIS Express 系统任务栏图标,然后点击“退出”或“停止站点”:
-
![](https://images2017.cnblogs.com/blog/913142/201802/913142-20180209143349341-590132942.png)
- 如果是在非调试模式下运行 VS 的,请按 F5 以在调试模式下运行。
- 如果是在调试模式下运行 VS 的,请停止调试程序并按 F5。
应用将显示设定为种子的数据:
![](https://images2017.cnblogs.com/blog/913142/201802/913142-20180209143428982-1168616203.png)
但是这里存在另外一个问题:如果一部分数据库数据表中已经存在数据了,现在又想初始化另外的数据表怎么办?
改造一下
if (!context.Movie.Any()) { //return; // DB has been seeded context.Movie.AddRange( new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-2-12"), Genre = "Romantic Comedy", Price = 7.99M }, new Movie { Title = "Ghostbusters", ReleaseDate = DateTime.Parse("1984-3-13"), Genre = "Comedy", Price = 8.99M }, new Movie { Title = "Ghostbusters 2", ReleaseDate = DateTime.Parse("1986-2-23"), Genre = "Comedy", Price = 9.99M }, new Movie { Title = "Rio Bravo", ReleaseDate = DateTime.Parse("1959-4-15"), Genre = "Western", Price = 3.99M } ); } if (!context.Class.Any()) { //return; context.Class.AddRange( new Class { Name = "国产电影", bz = "国产电影备注" }, new Class { Name = "日韩电影", bz = "日韩电影备注" }); } context.SaveChanges();
测试:删掉任意一个数据库中的数据,然后重启,原本存在数据的数据表不会有改动,没有数据的数据表将写入默认数据。