我的问题是我正在尝试使用数据来构建实体框架核心数据库,在我看来下面的代码显示了工作。我已经意识到这不应该在ApplicationDbContext
构造函数中调用,应该从startup
调用,但我不知道如何做到这一点。
编辑:根据Ketrex提供的解决方案,我的解决方案如下:
Startup.cs:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
...
app.ApplicationServices.GetRequiredService<ApplicationDbContext>().Seed();
}
种子延伸:
public static class DbContextExtensions
{
public static void Seed(this ApplicationDbContext context)
{
// Perform database delete and create
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
// Perform seed operations
AddCountries(context);
AddAreas(context);
AddGrades(context);
AddCrags(context);
AddClimbs(context);
// Save changes and release resources
context.SaveChanges();
context.Dispose();
}
private static void AddCountries(ApplicationDbContext context)
{
context.AddRange(
new Country { Name = "England", Code = "En" },
new Country { Name = "France", Code = "Fr" }
);
}
...
}
我知道在实体框架的优先级列表中播种数据库是相当高的,但如果有一些关于如何实现这个简单任务或至少提供临时工作的文档会很好。如果有人可以就如何做到这一点提供一些指导,我们将不胜感激。我觉得我接近一个解决方案,但只能把它拼凑起来。
感谢您的帮助。
答案 0 :(得分:11)
假设您使用的是内置DI容器,这是一种可以实现此目的的方法。
在启动类的Configure方法中引用种子方法,并将IApplicationBuilder对象作为参数而不是DbContext传递,如下所示:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//...
// Put this at the end of your configure method
DbContextSeedData.Seed(app);
}
接下来,修改种子方法以接受IApplicationBuilder实例。然后你就可以启动DbContext的一个实例,并执行种子操作,如下所示:
public static void Seed(IApplicationBuilder app)
{
// Get an instance of the DbContext from the DI container
using (var context = app.ApplicationServices.GetRequiredService<ApplicationDbContext>())
{
// perform database delete
context.Database.EnsureDeleted;
//... perform other seed operations
}
}
答案 1 :(得分:4)
您还可以使用Startup.cs ConfigureServices
方法使ApplicationDbContext可用(将dbcontext注册为服务):
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Startup.Configuration["connectionStrings:DBConnectionString"];//this line is not that relevant, the most important thing is registering the DbContext
services.AddDbContext<ApplicationDbContext>(o => o.UseSqlServer(connectionString));
}
然后将您的ApplicationDbContext作为依赖项添加到Configure
方法中,该方法将调用种子扩展方法。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ApplicationDbContext myApplicationDbContext)
{
//...
myApplicationDbContext.Seed();
}
最后种子方法可以快速检查一个重要的表,因为重建db可能太重了:
public void Seed()
{
//....
if(context.Countries.Any())
return;
//...
}
我希望它可以帮助你或其他人,至少作为另一种选择。
答案 2 :(得分:0)
如果您想从单独的类库中运行EF代码并执行Seeding,则可以执行以下操作。这是使用TSQL ...
1) 创建一个新的类库。 使用NuGet ...
添加以下依赖项Microsoft.AspNetCore
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
2)将软件包管理器控制台指向此项目并运行...
PM> add-migration Seeder01
...然后
PM> update-database
这会让您进行空迁移。
3)将更新编写为类似......
的脚本using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;
using System.IO;
namespace Test02.Data.Migrations
{
public partial class Seeder01 : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
string sql = string.Empty;
sql = "SET IDENTITY_INSERT State ON;";
sql += "Insert into State (Id, Name) values ";
sql += "(2, 'NSW'),";
sql += "(3, 'VIC'),";
sql += "(4, 'QLD'),";
sql += "(5, 'SA')";
sql += ";";
sql += "SET IDENTITY_INSERT State OFF;";
migrationBuilder.Sql(sql);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
string sql = string.Empty;
sql = "delete State;";
migrationBuilder.Sql(sql);
}
}
}
4)使用...
恢复到先前的迁移PM> add-migration {PriorMigrationName}
重新加载种子迁移并更新数据库......
PM> add-migration Seeder01
PM> update-database