简体   繁体   English

我应该把Database.EnsureCreated放在哪里?

[英]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. 我有一个Entity Framework Core + ASP.NET Core应用程序,当我的应用程序启动时,我想确保创建数据库,并最终(一旦我有迁移)我想确保它们也运行。

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. 最初我将Database.EnsureCreated()放入我的DbContext的构造函数中,但是每次有人点击我的应用程序时它都会运行,因为DbContext都会创建一个新的DbContext实例。

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. 我试着把它放到我的启动代码中,但我需要一个我的DbContext实例才能做到这一点,目前还不清楚如何获得一个。 I am configuring EF as so: 我正在配置EF如下:

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. 我没有看到从服务集合中获取DbContext实例的方法,我没有看到任何适当的单例来注入DbContext,所以我可以做一些一次性初始化。

So what is the best place to ensure some code related to my DbContext is called once per application run? 那么确保一些与我的DbContext相关的代码在每个应用程序运行时被调用一次的最佳位置是什么?

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 ). 在撰写本文时,没有一个“正确”的地方在应用程序启动时运行代码,使其在请求范围内执行(请参阅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 ) 目前,解决方法是执行以下操作,但它不适用于更复杂的多应用程序方案(请参阅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();
        }
    }
}

I wonder why you would run to run EnsureCreated as part of your service anyway. 我想知道为什么你会跑去运行EnsureCreated作为你服务的一部分。 Do you really want your webserver to create or update the database schema? 真的希望您的Web服务器创建或更新数据库架构吗? 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. 此外,这将要求您为webserver数据库用户授予更改数据库架构的权限。 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. 我建议您创建数据库并在您自己运行的小实用程序中应用迁移,而不是作为Web应用程序的一部分。

I think zmbq 's suggestion is a correct one and there is a way to ensure that migrations are run along with the deployment, so that binaries and database changes are in sync, using Visual Studio's Publish functionality. 我认为zmbq的建议是正确的,并且有一种方法可以确保迁移与部署一起运行,以便使用Visual Studio的发布功能使二进制文件和数据库更改保持同步。

When publishing against an IIS instance, one can specify target database connection string to use to also run required migrations: 针对IIS实例发布时,可以指定要用于运行所需迁移的目标数据库连接字符串:

发布时使用的实体框架迁移

This will ensure that changes are applied only when needed (not every time application starts) and that application runs using the least required database rights (ie database writer, reader etc.) as opposed to rights to alter tables, create indexes etc. 这将确保仅在需要时(不是每次应用程序启动时)应用更改,并且应用程序使用最少的数据库权限(即数据库编写器,读取器等)运行,而不是更改表,创建索引等的权限。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Database.EnsureCreated无法正常工作 - Database.EnsureCreated not working EntityFramework Core Database.EnsureCreated不会创建数据库 - EntityFramework Core Database.EnsureCreated doesn't create database Database.EnsureCreated似乎不是在创建数据库(xamarin.forms) - Database.EnsureCreated does not seem that it's creating a database (xamarin.forms) 如何在Database.EnsureCreated()和EF Xamarin.Forms之后使用Database.Migration() - How to use Database.Migration() after Database.EnsureCreated() EF Xamarin.Forms EF Core Database.EnsureCreated 获取创建表 SQL 并且不向数据库发送请求 - EF Core Database.EnsureCreated get creating table SQL and without sending request to database Database.EnsureCreated EF 7 ASP.NET 5 MVC 6处的堆栈溢出异常 - Stack Overflow exception at Database.EnsureCreated EF 7 ASP.NET 5 MVC 6 如何使用 .NET 6 在 aspnet 核心 Web 应用程序中执行 database.ensurecreated()? - How do you do database.ensurecreated() in aspnet core web application using .NET 6? 我应该在哪里放置UpdatePanel - Where should I put my UpdatePanel 我应该在哪里放置MEF接口? - Where should I put the interfaces for MEF? MEF:我应该把CompositionContainer放在哪里? - MEF: Where should I put the CompositionContainer?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM