不幸的是,Entity Framwork Core不再支持IDatabaseInitializer
:所以没有DropCreateDatabaseAlways.Seed()
和DropCreateDatabaseIfModelChanges.Seed()
。 : - (
所以那里的人写了很多东西:
DbContext
的具体实例的帮助下,如果#1(作为数据库为空)应用种子数据。我在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
的末尾会破坏实体框架工具链:
PM> Add-Migration MyMigration
PM> Update-Datebase
以及:
PM> Update-Datebase NameOfPreviousMigration
PM> Remove-Migration
这些命令行开关使用方法Program.BuildWebHost()
来调用我的Startup
和Startup.ConfigureServices()
以及Startup.Configure()
(即使不需要:{{3} }})。更糟糕的是,如果我打电话Remove-Migration
,就会让粉丝点击粉丝:Remove-Migration
→Startup.Configure()
→迁移和种子(数据库是最新迁移=没有要移除的迁移)→错误:
迁移&#39; 20170914084432_MyMigration&#39;已经应用于数据库。还原它然后再试一次。如果迁移已应用于其他数据库,请考虑使用新迁移恢复其更改。
简单地说,如何从工具链中分别运行我的Migrate&amp; Seed内容告诉我Startup.Configure()
的工具链?
请注意:我不想使用IDesignTimeDbContextFactory
因为......
IConfiguration
的实例来检索连接字符串。ConfigurationBuilder
也是多余的(https://github.com/aspnet/EntityFrameworkCore/issues/9076)。特别是在EF Core 2.0中它很麻烦且错误,因为你总是需要模仿WebHost.CreateDefaultBuilder()
。IDesignTimeDbContextFactory
到位Program.BuildWebHost()
,最后Startup.ConfigureServices()
仍然被调用(Get ConnectionString from appsettings.json instead of being hardcoded in .NET Core 2.0 App是一个糟糕的解决方法!)。答案 0 :(得分:0)
经过几个小时的猜测和失败,我放弃了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
注册为服务。 (目前)没有办法指向另一个班级!如果你尝试,你会得到:
Scaffolding无法编辑Startup类以注册新的Context 使用依赖注入。确保有一个Startup类和一个 其中包含ConfigureServices方法和Configuration属性。
BuildWebHost
方法。所以你需要在这里使用Startup
。否则你会得到这个误导性的消息:
没有为此对象定义无参数构造函数。
BuildWebHost
方法访问启动类(与scaffolding相同)。 结论:
因此,如果您不想在每次添加新Controller或添加/删除迁移时调用迁移和种子,则必须提供精简Startup
类并将(运行时)内容放在其他位置! / p>
您可以在设计时和运行时启动时创建一个重用ConfigureServices()
方法的基类。 (请记住,脚手架在修改Startup
的基本类型时总是会失败。但据我所知,只有通过将MyDbContext
注册为服务才能实现。这应该是可管理的。)