[英]Seeding Data with Entity Framework 3.0 with Model or Migration?
[英]Establish auto migration and seeding without spoiling Entity Framework toolchain
不幸的是实体Framwork核心不支持IDatabaseInitializer
小号了:所以没有DropCreateDatabaseAlways.Seed()
和DropCreateDatabaseIfModelChanges.Seed()
:-(
因此人们在那里写了很多东西来:
DbContext
的具体实例的帮助下应用种子数据。 我在Startup.Configure
的末尾提出了以下几行内容:我在其中注入了IApplicationBuilder app
和IHostingEnvironment env
:
using (var scope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
using (var context = scope.ServiceProvider.GetService<MyDbContext>())
{
var hasPendingMigrations = context.Database.GetPendingMigrations().Any();
if (hasPendingMigrations) {
var needsSeeding = !context.Database.GetAppliedMigrations().Any(); // No migration yet (no database or it's empty).
context.Database.Migrate(); // Create/update schema (creates database if necessary).
if (needsSeeding) {
Seed(context);
if (env.IsDevelopment()) {
SeedWithDummyData(context);
}
}
}
}
}
但是将这些行放在Startup.Configure
的末尾会破坏Entity Framework工具链:
PM> Add-Migration MyMigration
PM> Update-Datebase
以及:
PM> Update-Datebase NameOfPreviousMigration
PM> Remove-Migration
这些Commandlet正在使用Program.BuildWebHost()
方法来调用我的Startup
和Startup.ConfigureServices()
以及Startup.Configure()
(即使不需要: https : //github.com/aspnet/EntityFrameworkCore/issues/ 9076 )。 如果我打电话给Remove-Migration
更糟了: Remove-Migration
→ Startup.Configure()
→迁移和种子(数据库处于最新迁移状态=无法删除迁移)→错误:
迁移“ 20170914084432_MyMigration”已应用于数据库。 还原它,然后再试一次。 如果已将迁移应用于其他数据库,请考虑使用新的迁移还原其更改。
简而言之,如何将Migrate&Seed东西从工具链中移出,分别告诉我Startup.Configure()
的工具链手?
请记住:我不喜欢使用IDesignTimeDbContextFactory
因为...
IConfiguration
实例来检索连接字符串。 ConfigurationBuilder
也是多余的( 从appsettings.json获取ConnectionString而不是在.NET Core 2.0 App中进行硬编码 )。 特别是在EF Core 2.0中,它非常麻烦且容易出错,因为您始终必须模仿WebHost.CreateDefaultBuilder()
。 IDesignTimeDbContextFactory
,也仍然会调用Program.BuildWebHost()
并最终调用Startup.ConfigureServices()
(并且https://github.com/aspnet/EntityFrameworkCore/issues/9076#issuecomment-313278753是一个很差的解决方法!)。 经过数小时的猜测和失败,我放弃了Startup
课! 因此,我现在将RuntimeStartup
用于运行时,并将几乎空的Startup
用于所有设计时任务(支架和迁移):
public class Program
{
public static void Main(string[] args)
{
WebHost.CreateDefaultBuilder(args)
.UseStartup<RuntimeStartup>()
.Build()
.Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}
为什么这么复杂?
Startup
类以将MyDbContext
注册为服务。 (当前)无法指向另一个课程! 如果尝试,您将获得:
脚手架无法编辑启动类以使用依赖注入来注册新的上下文。 确保其中包含一个Startup类以及一个ConfigureServices方法和Configuration属性。
BuildWebHost
方法。 因此,您也需要在此处使用Startup
。 否则,您会收到以下误导性消息:
没有为此对象定义无参数构造函数。
BuildWebHost
方法来获取启动类(与脚手架相同)。 结论:
因此,如果您不想在每次添加新的Controller或添加/删除迁移时都调用迁移和播种,则必须提供一个精益的Startup
类并将(运行时)内容放到其他地方!
由您决定在设计时和运行时启动时重用ConfigureServices()
方法来创建基类。 (请记住,脚手架在修改Startup
基本类型时总是会失败。但是据我所知,只有将MyDbContext
注册为服务才会发生。这应该是可管理的。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.