entity framework7 RC 1和ASP.NET MVC 6中的种子初始数据
似乎在Entity Framework 7中还没有对种子数据的原生支持( https://github.com/aspnet/EntityFramework/issues/629 )。
Microsoft提供的模板代码中没有DbMigrationsConfiguration
类,也没有Seed
方法。
那么如何在使用Entity Framework 7 RC 1的ASP.NET MVC 6 Web应用程序中播种数据呢?
我为自己找到了一个临时的解决方法。
我们可以创建一个方法SeedData
,它扩展IApplicationBuilder
然后通过GetService
方法获取我们的数据库上下文类的实例,并使用它来播种数据。
以下是我的扩展方法的样子:
using Microsoft.AspNet.Builder; using Microsoft.Extensions.DependencyInjection; public static class DataSeeder { // TODO: Move this code when seed data is implemented in EF 7 /// /// This is a workaround for missing seed data functionality in EF 7.0-rc1 /// More info: https://github.com/aspnet/EntityFramework/issues/629 /// /// /// An instance that provides the mechanisms to get instance of the database context. /// public static void SeedData(this IApplicationBuilder app) { var db = app.ApplicationServices.GetService(); // TODO: Add seed logic here db.SaveChanges(); } }
要使用它,请app.SeedData();
应用程序Startup
类的Configure
方法中的行(位于名为Startup.cs
文件中的Web项目中)。
// This method gets called by the runtime. // Use this method to configure the HTTP request pipeline. public void Configure( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.SeedData(); // Other configuration code }
适用于EF Core RTM 1.0和ASP.NET Core RTM 1.0
首先创建种子方法。 这里因为我们不在当前请求的范围内,所以我们必须手动创建它:
using System.Collections.Generic; using System.Linq; using Core1RtmEmptyTest.Entities; using Microsoft.Extensions.DependencyInjection; namespace Core1RtmEmptyTest.Migrations { public static class ApplicationDbContextSeedData { public static void SeedData(this IServiceScopeFactory scopeFactory) { using (var serviceScope = scopeFactory.CreateScope()) { var context = serviceScope.ServiceProvider.GetService(); if (!context.Persons.Any()) { var persons = new List { new Person { FirstName = "Admin", LastName = "User" } }; context.AddRange(persons); context.SaveChanges(); } } } } }
然后指定ApplicationDbContext的正确生命周期
public void ConfigureServices(IServiceCollection services) { services.AddDbContext(ServiceLifetime.Scoped);
最后从Configure
方法调用SeedData()
方法
public void Configure(IServiceScopeFactory scopeFactory) { scopeFactory.SeedData();
我在我的Startup.cs
创建了私有的Seed()
方法,但我也喜欢你的方法,因为它不仅可以在应用程序启动时使用。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { this.Seed(); } private void Seed() { using (var db = new MyDbContext()) { db.Database.Migrate(); // Seed code db.SaveChanges(); } }
来自EF / MVC简介 ,只需:
- 依赖项 – 将您的
DbContext
(下面的DbContext
)直接注入Startup.Configure()
* - 将你的
DbContext
传递给一个函数(下面的DbInitializer.Initialize
),它执行以下操作:- 确保创建数据库或迁移数据库;
context.Database.EnsureCreated();
考虑context.Database.Migrate();
- 如果已经播种,
if (context.Students.Any()) { return; }
返回ifif (context.Students.Any()) { return; }
if (context.Students.Any()) { return; }
- else seed
context.Students.Add({...}); context.SaveChanges();
context.Students.Add({...}); context.SaveChanges();
- 确保创建数据库或迁移数据库;
像这儿:
public void Configure(..., ..., SchoolContext context) { ... DbInitializer.Initialize(context); }
…
public static class DbInitializer { public static void Initialize(SchoolContext context) { context.Database.EnsureCreated(); // Look for any students. if (context.Students.Any()) { return; // DB has been seeded } var students = new Student[] { new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")}, ... }; foreach (Student s in students) { context.Students.Add(s); } context.SaveChanges(); ...
*dependency injectionStartup.Configure()
是为什么我的答案是值得的(尽管已经接受了另一个答案。)
- 依赖性 – 将您的
DbContext
注入Startup.Configure()
是在EF / MVC Intro中完成的 - 这里没有其他答案只是dependency injection到Configure; 它们是
GetService()
和/或GetRequiredService()
,或者实例化一个新的DbContext
。 您可能不需要那么多代码。 然后,您可能需要那么多代码,(例如,如果处理了Dependency-Injected DbContext, 这是创建新Scope所必需的GetService()
。如果我错误的话,请下载/编辑/评论。
您可以在ApplicationDbContext中创建静态种子方法,并将IApplicationBuilder作为参数传递。 然后在Startup.cs
调用此方法。
public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions options) : base(options) { } public static void Seed(IApplicationBuilder applicationBuilder) { using (var context=applicationBuilder.ApplicationServices.GetRequiredService ()) { context.Database.EnsureDeleted(); context.Database.EnsureCreated(); for(int i = 1; i< 1000; i++) { context.Movies.Add(new Movie { Genre = "Action", ReleaseDate =DateTime.Today, Title = "Movie "+i }); } context.SaveChanges(); } } public DbSet Movies { get; set; } }
在Startup.cs
Configure()
方法中,调用ApplicationDbContext.Seed(app)
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } app.UseStaticFiles(); app.UseIdentity(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); ApplicationDbContext.Seed(app); }
- 如何阅读ASP.NET Core Response.Body?
- 在MVC 6中,如何在视图中编码复选框列表并将选中的值传递给控制器?
- 如何在ASP.NET Core 1.0的DI中的Startup类中添加IHttpContextAccessor?
- 如何正确地在MVC6中注入HttpContext
- 如何在ASP.NET Core中将角色添加到Windows身份validation
- ASP.NET 5中的dependency injection和对象处理
- MVC .Net核心模型validation – 值”无效。 错误
- MVC ICollection ValidationState始终设置为Skipped
- ServiceFilter和TypeFilter – 注入这些filter有什么区别?