Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where should I put Database.EnsureCreated?

I have an Entity Framework Core + ASP.NET Core application and when my application starts up I want to ensure that the database is created, and eventually (once I have migrations) I want to ensure that those are also run.

Initially I put Database.EnsureCreated() into the constructor of my DbContext but that appears to run every time someone hits my application since a new instance of the DbContext is created each time.

I tried to put it into my startup code, but I need an instance of my DbContext to do that and it is unclear how exactly to get one. I am configuring EF as so:

serviceCollection.AddEntityFramework()
    .AddSqlServer()
    .AddDbContext<Models.MyContext>(options => options.UseSqlServer(...));

I don't see a way to get an instance of the DbContext from the service collection, and I don't see any appropriate singleton to inject a DbContext into so I can do some one-time initialization.

So what is the best place to ensure some code related to my DbContext is called once per application run?

like image 848
Micah Zoltu Avatar asked Apr 30 '16 17:04

Micah Zoltu


People also ask

What is database EnsureCreated?

EnsureCreated. EnsureCreated will create the database if it doesn't exist and initialize the database schema. If any tables exist (including tables for another DbContext class), the schema won't be initialized.

How do I apply EF core migrations?

Migrations are enabled by default in EF Core. They are managed by executing commands. If you have Visual Studio, you can use the Package Manager Console (PMC) to manage migrations. Alternatively, you can use a command line tool to execute Entity Framework CLI commands to create a migration.

How do I turn on automatic migration in Entity Framework?

Open the Package Manager Console from Tools → Library Package Manager → Package Manager Console and then run the enable-migrations –EnableAutomaticMigration:$true command (make sure that the default project is the project where your context class is).

How do I enable auto migration in .NET core?

Run the Enable-Migrations –EnableAutomaticMigrations command in Package Manager Console This command has added a Migrations folder to our project. This new folder contains one file: The Configuration class. This class allows you to configure how Migrations behaves for your context.


2 Answers

At the time of this writing, there is not a "correct" place to run code on application startup such that it executes within the request scope (see https://github.com/aspnet/Hosting/issues/373).

For now, the workaround is to do the following, but it won't work in more complex multi-application scenarios (see https://github.com/aspnet/EntityFramework/issues/3070#issuecomment-142752126)

public class Startup
{
    ...

    public void Configure(IApplicationBuilder applicationBuilder, ...)
    {
        ...
        // NOTE: this must go at the end of Configure
        var serviceScopeFactory = applicationBuilder.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
        using (var serviceScope = serviceScopeFactory.CreateScope())
        {
            var dbContext = serviceScope.ServiceProvider.GetService<MyDbContext>();
            dbContext.Database.EnsureCreated();
        }
    }
}
like image 122
Micah Zoltu Avatar answered Oct 09 '22 15:10

Micah Zoltu


I wonder why you would run to run EnsureCreated as part of your service anyway. Do you really want your webserver to create or update the database schema? Why would the webserver be up and serving request if the database is not up to date?

Do you really trust your migrations so much that they don't ruin data when executed, that you don't want to test the data after running them?

In addition, this will require you to give the webserver database user permissions to change the database schema. This is a vulnerability in itself - someone taking over your webserver will be able to modify your database schema.

I suggest you create the database and apply migrations in a small utility you run yourself, not as part of your web application.

like image 45
zmbq Avatar answered Oct 09 '22 16:10

zmbq