在Entity Framework Core中自动创建数据库

dea*_*dob 70 c# sqlite entity-framework-core .net-core

我的应用程序被移植到.NET核心将使用新的EF核心与SQLite.我想在首次运行应用程序时自动创建数据库和表结构.根据EF核心文档,这是使用手动命令完成的

dotnet ef migrations add MyFirstMigration

dotnet ef database update
Run Code Online (Sandbox Code Playgroud)

但是,我不希望最终用户输入这些命令,并且希望让应用程序创建并设置数据库以供首次使用.对于EF 6,有类似的功能

Database.SetInitializer(new CreateDatabaseIfNotExists<MyContext>());
Run Code Online (Sandbox Code Playgroud)

但在EF Core中,这些似乎并不存在.我找不到任何关于EF核心等效的示例或文档,并且在EF核心文档的缺失功能列表中没有提到.我已经设置了模型类,所以我可以编写一些代码来基于模型初始化数据库,但如果框架自动执行此操作,则会更容易.我不想自动构建模型或迁移,只需在新数据库上创建表结构.

我在这里遗漏了什么或者在EF核心中缺少自动创建表功能吗?

Ric*_*ana 102

如果已创建迁移,则可以在Startup.cs中执行它们,如下所示.

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 {
      using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
      {
            var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            context.Database.Migrate();
      }

      ...
Run Code Online (Sandbox Code Playgroud)

这将使用您添加的迁移创建数据库和表.

如果您没有使用Entity Framework迁移,而只需要在第一次运行时完全按照在上下文类中创建的DbContext模型创建,那么您可以使用:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
 {
      using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
      {
            var context = serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
            context.Database.EnsureCreated();
      }

      ...
Run Code Online (Sandbox Code Playgroud)

代替.

如果您需要在确定数据库创建之前删除它,请致电:

            context.Database.EnsureDeleted();
Run Code Online (Sandbox Code Playgroud)

在你调用EnsureCreated()之前

改编自:http://docs.identityserver.io/en/release/quickstarts/8_entity_framework.html? highlight = entity

  • 对不起,我在回答中犯了一个错误,如果你没有使用迁移,可以使用命令context.Database.EnsureCreated()/ EnsureDeleted(),更多详情请访问https://blogs.msdn.microsoft.com/DOTNET/2016/9月29日/实施播种定制的约定,和拦截功能于EF-核心-1-0 / (2认同)
  • 如果您需要两种解决方案怎么办 我们刚刚将我们的应用程序移植到UWP并开始使用EF Core,这意味着一些用户需要从头开始创建数据库,而其他用户已经拥有数据库.有没有办法确保第一次迁移只创建初始表(如果它们尚不存在)?你的答案似乎没有涵盖这个或我错过了什么? (2认同)

sus*_*oo_ 27

我的回答与里卡多的答案非常相似,但我觉得我的方法稍微简单一点,因为他的using功能有很多,我甚至不确定它在更低层次上是如何工作的.

因此,对于那些想要为您创建数据库的简单而干净的解决方案的用户而言,您确切地知道幕后发生了什么,这适合您:

public Startup(IHostingEnvironment env)
{
    using (var client = new TargetsContext())
    {
        client.Database.EnsureCreated();
    }
}
Run Code Online (Sandbox Code Playgroud)

这几乎意味着在DbContext您创建的内容中(在本例中,我的名称被调用TargetsContext),您可以使用它的实例DbContext来确保在应用程序中运行Startup.cs时创建类中定义的表.

  • 正如来自[here](https://github.com/aspnet/EntityFrameworkCore/issues/3160)的信息:`EnsureCreated`完全绕过迁移并只为您创建架构,您不能将其与迁移混合使用.`EnsureCreated`专为测试或快速原型设计而设计,您可以在每次删除和重新创建数据库时使用.如果您正在使用迁移并希望在app start上自动应用它们,那么您可以使用`context.Database.Migrate()`代替. (8认同)
  • @ThomasSchneiter哦,很酷!感谢那!我不知道. (2认同)

Pau*_*ler 18

对于 EF Core 2.0+,我不得不采取不同的方法,因为他们更改了 API。截至 2019 年 3 月,Microsoft 建议您将数据库迁移代码放在应用程序入口类中,但放在 WebHost 构建代码之外。

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();
        using (var serviceScope = host.Services.CreateScope())
        {
            var context = serviceScope.ServiceProvider.GetRequiredService<PersonContext>();
            context.Database.Migrate();
        }
        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}
Run Code Online (Sandbox Code Playgroud)


Joh*_*icz 11

如果通过Startup.cs中的Configure参数列表获取上下文,则可以执行以下操作:

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  LoggerFactory loggerFactory,
    ApplicationDbContext context)
 {
      context.Database.Migrate();
      ...
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言,这是最好的解决方案:您不必关心任何服务甚至数据库上下文,您只需使用通过依赖注入获得的上下文即可。好的! (2认同)

小智 6

如果您尚未创建迁移,则有2个选项

1.从应用程序Main创建数据库和表:

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();
Run Code Online (Sandbox Code Playgroud)

2.如果数据库已存在,则创建表:

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();
Run Code Online (Sandbox Code Playgroud)

感谢Bubi的回答

  • 您的服务是什么? (2认同)