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


100

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

dotnet ef migrations add MyFirstMigration

dotnet ef database update

但是,我不希望最终用户输入这些命令,而是希望该应用创建并设置数据库以供首次使用。对于EF 6,具有以下功能

Database.SetInitializer(new CreateDatabaseIfNotExists<MyContext>());

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

我在这里缺少什么吗?还是EF核心缺少自动创建表功能?

Answers:


146

如果创建了迁移,则可以按以下步骤在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();
      }

      ...

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

如果您不使用Entity Framework Migrations,而是只需要在初次运行时完全按照上下文类中的方式创建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();
      }

      ...

代替。

如果需要先删除数据库,然后再确保已创建,请致电:

            context.Database.EnsureDeleted();

在您致电之前 EnsureCreated()

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


1
我对EF还是很陌生,我首先使用EF 6代码创建了用于定义数据结构的类,这些代码首先使用当前数据库文件从Visual Studio中“从数据库创建”。然后,将它们剪切/粘贴到新的dotnet核心VS解决方案中-所以我想这些不是迁移。这是否意味着我必须先创建一个迁移文件,然后才能使用上述代码?
deandob

2
对不起,我在回答中犯了一个错误,如果您不使用迁移,则可以使用命令context.Database.EnsureCreated()/ EnsureDeleted(),更多详细信息请参见blogs.msdn.microsoft.com/dotnet/2016 / 09/29 /…
Ricardo Fontana

2
如果您同时需要两种解决方案怎么办?我们刚刚将应用程序移植到UWP并开始使用EF Core,这意味着一些用户需要从头开始创建数据库,而其他用户已经拥有该数据库。有什么方法可以确保第一次迁移只创建不存在的初始表?您的答案似乎无法解决这个问题,或者我错过了什么吗?
Lars Udengaard '18

33

我的答案与Ricardo的答案非常相似,但是我觉得我的方法要简单一些,仅仅是因为他的using功能发生了很大的变化,我什至不知道它在较低级别上是如何工作的。

因此,对于那些想要一个简单,干净的解决方案为您创建数据库的人,您可以确切地了解幕后发生的事情,这是给您的:

public Startup(IHostingEnvironment env)
{
    using (var client = new TargetsContext())
    {
        client.Database.EnsureCreated();
    }
}

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


10
就像这里的信息:EnsureCreated完全绕过迁移并只为您创建模式一样,您不能将其与迁移混在一起。EnsureCreated专为测试或快速原型设计,您可以每次删除并重新创建数据库。如果您正在使用迁移,并希望在应用启动时自动应用它们,则可以context.Database.Migrate()改用。
Thomas Schneiter '17

这回答了我的困惑,为什么我的连接字符串不起作用... :(因此数据库不是自动创建的,您必须指定在DbContext构造函数中完成的Database.EnsureCreated()。非常感谢,这使我摆脱了三天的困境。 X_X
pampi

只是想注意一下,我只是尝试将其粘贴到我的启动文件中,而VS2019通知我,IHostingEnvironment现在已弃用,推荐的替代方法是Microsoft.AspNetCore.Hosting.IWebHostEnvironment
ctrl-z请在

18

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

public void Configure(IApplicationBuilder app, IHostingEnvironment env,  LoggerFactory loggerFactory,
    ApplicationDbContext context)
 {
      context.Database.Migrate();
      ...

1
恕我直言,这是最好的解决方案:您不必关心任何服务,甚至DB上下文,您都可以使用通过依赖注入获得的上下文。真好!
Tobias

12

对于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>();
}

7

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

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

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();

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

var context = services.GetRequiredService<YourRepository>();
context.Database.EnsureCreated();
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();

感谢布比的回答


2
您的服务是什么?
MichaelMao

所有我读节目围绕移民说:“不要用大发警告的文档EnsureCreatedEnsureDeletedDatabase.Migrate将失败”
mwilson
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.