在 Entity Framework 7 RC 1 和 ASP.NET MVC 6 中播种初始数据
Seed initial data in Entity Framework 7 RC 1 and ASP.NET MVC 6
Entity Framework 7 似乎还没有原生支持种子数据 (https://github.com/aspnet/EntityFramework/issues/629)。
微软提供的模板代码中没有DbMigrationsConfiguration
class,没有Seed
方法
那么如何在使用 Entity Framework 7 RC 1 的 ASP.NET MVC 6 Web 应用程序中播种数据?
我为自己找到了一个临时解决方法。
我们可以创建一个扩展 IApplicationBuilder
的方法 SeedData
,然后通过 GetService
方法获取我们的数据库上下文 class 的一个实例,并将其用于播种数据.
这是我的扩展方法的样子:
using Microsoft.AspNet.Builder;
using Microsoft.Extensions.DependencyInjection;
public static class DataSeeder
{
// TODO: Move this code when seed data is implemented in EF 7
/// <summary>
/// This is a workaround for missing seed data functionality in EF 7.0-rc1
/// More info: https://github.com/aspnet/EntityFramework/issues/629
/// </summary>
/// <param name="app">
/// An instance that provides the mechanisms to get instance of the database context.
/// </param>
public static void SeedData(this IApplicationBuilder app)
{
var db = app.ApplicationServices.GetService<ApplicationDbContext>();
// TODO: Add seed logic here
db.SaveChanges();
}
}
要使用它,请将 app.SeedData();
行放入应用程序 Startup
class 的 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
}
我在 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 Core RTM 1.0 和 ASP.NETCore 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<ApplicationDbContext>();
if (!context.Persons.Any())
{
var persons = new List<Person>
{
new Person
{
FirstName = "Admin",
LastName = "User"
}
};
context.AddRange(persons);
context.SaveChanges();
}
}
}
}
}
然后指定 ApplicationDbContext 的正确生命周期
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(ServiceLifetime.Scoped);
最后从Configure
方法中调用SeedData()
方法
public void Configure(IServiceScopeFactory scopeFactory)
{
scopeFactory.SeedData();
您可以在 ApplicationDbContext 中创建静态种子方法并将 IApplicationBuilder 作为参数传递。然后在Startup.cs
中调用这个方法。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public static void Seed(IApplicationBuilder applicationBuilder)
{
using (var context=applicationBuilder.ApplicationServices.GetRequiredService<ApplicationDbContext>())
{
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<Movie> Movies { get; set; }
}
在Configure()
方法里面Startup.cs
,调用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);
}
来自 EF/MVC intro,刚刚:
- 依赖项-将您的
DbContext
(下面的 SchoolContext
)直接注入 Startup.Configure()
*
- 将您的
DbContext
传递给函数(下面的 DbInitializer.Initialize
),该函数执行如下操作:
- 确保数据库是 created or that it's migrated;
context.Database.EnsureCreated();
考虑 context.Database.Migrate();
- returns 如果已经播种
if (context.Students.Any()) { return; }
- 其他种子
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();
...
*对 Startup.Configure()
的依赖注入是我的回答有价值的原因(即使另一个答案已经被接受。)
- 将您的
DbContext
依赖注入 Startup.Configure()
是在 EF/MVC Intro 中完成的
- 这里没有其他答案只是依赖注入配置;他们要么
GetService()
and/or GetRequiredService()
,要么 实例化一个新的 DbContext
。您可能不需要那么多代码。再一次,你可能需要那么多代码,(即如果依赖注入的DbContext被处理,which is where the GetService()
is necessary to create a new Scope.。如果我弄错了什么请downvote/edit/comment .
Entity Framework 7 似乎还没有原生支持种子数据 (https://github.com/aspnet/EntityFramework/issues/629)。
微软提供的模板代码中没有DbMigrationsConfiguration
class,没有Seed
方法
那么如何在使用 Entity Framework 7 RC 1 的 ASP.NET MVC 6 Web 应用程序中播种数据?
我为自己找到了一个临时解决方法。
我们可以创建一个扩展 IApplicationBuilder
的方法 SeedData
,然后通过 GetService
方法获取我们的数据库上下文 class 的一个实例,并将其用于播种数据.
这是我的扩展方法的样子:
using Microsoft.AspNet.Builder;
using Microsoft.Extensions.DependencyInjection;
public static class DataSeeder
{
// TODO: Move this code when seed data is implemented in EF 7
/// <summary>
/// This is a workaround for missing seed data functionality in EF 7.0-rc1
/// More info: https://github.com/aspnet/EntityFramework/issues/629
/// </summary>
/// <param name="app">
/// An instance that provides the mechanisms to get instance of the database context.
/// </param>
public static void SeedData(this IApplicationBuilder app)
{
var db = app.ApplicationServices.GetService<ApplicationDbContext>();
// TODO: Add seed logic here
db.SaveChanges();
}
}
要使用它,请将 app.SeedData();
行放入应用程序 Startup
class 的 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
}
我在 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 Core RTM 1.0 和 ASP.NETCore 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<ApplicationDbContext>();
if (!context.Persons.Any())
{
var persons = new List<Person>
{
new Person
{
FirstName = "Admin",
LastName = "User"
}
};
context.AddRange(persons);
context.SaveChanges();
}
}
}
}
}
然后指定 ApplicationDbContext 的正确生命周期
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(ServiceLifetime.Scoped);
最后从Configure
方法中调用SeedData()
方法
public void Configure(IServiceScopeFactory scopeFactory)
{
scopeFactory.SeedData();
您可以在 ApplicationDbContext 中创建静态种子方法并将 IApplicationBuilder 作为参数传递。然后在Startup.cs
中调用这个方法。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public static void Seed(IApplicationBuilder applicationBuilder)
{
using (var context=applicationBuilder.ApplicationServices.GetRequiredService<ApplicationDbContext>())
{
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<Movie> Movies { get; set; }
}
在Configure()
方法里面Startup.cs
,调用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);
}
来自 EF/MVC intro,刚刚:
- 依赖项-将您的
DbContext
(下面的SchoolContext
)直接注入Startup.Configure()
* - 将您的
DbContext
传递给函数(下面的DbInitializer.Initialize
),该函数执行如下操作:- 确保数据库是 created or that it's migrated;
context.Database.EnsureCreated();
考虑context.Database.Migrate();
- returns 如果已经播种
if (context.Students.Any()) { return; }
- 其他种子
context.Students.Add({...}); context.SaveChanges();
- 确保数据库是 created or that it's migrated;
在这里点赞:
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();
...
*对 Startup.Configure()
的依赖注入是我的回答有价值的原因(即使另一个答案已经被接受。)
- 将您的
DbContext
依赖注入Startup.Configure()
是在 EF/MVC Intro 中完成的
- 这里没有其他答案只是依赖注入配置;他们要么
GetService()
and/orGetRequiredService()
,要么 实例化一个新的DbContext
。您可能不需要那么多代码。再一次,你可能需要那么多代码,(即如果依赖注入的DbContext被处理,which is where theGetService()
is necessary to create a new Scope.。如果我弄错了什么请downvote/edit/comment .