【问题标题】:Where should I put Database.EnsureCreated?我应该把 Database.EnsureCreated 放在哪里?
【发布时间】:2016-08-25 19:03:50
【问题描述】:

我有一个 Entity Framework Core + ASP.NET Core 应用程序,当我的应用程序启动时,我想确保创建数据库,并且最终(一旦我进行迁移)我想确保这些也运行。

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

我试图将它放入我的启动代码中,但我需要一个 DbContext 的实例来执行此操作,目前还不清楚如何获得它。我正在这样配置 EF:

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

我没有看到从服务集合中获取 DbContext 实例的方法,也没有看到任何合适的单例来注入 DbContext,因此我可以进行一些一次性初始化。

那么,确保在每次应用程序运行时调用与我的 DbContext 相关的一些代码的最佳位置是什么?

【问题讨论】:

  • EnsureCreated 用于测试,不用于生产

标签: c# asp.net entity-framework-core


【解决方案1】:

在撰写本文时,还没有一个“正确”的地方可以在应用程序启动时运行代码以使其在请求范围内执行(请参阅https://github.com/aspnet/Hosting/issues/373)。

目前,解决方法是执行以下操作,但它不适用于更复杂的多应用场景(请参阅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();
        }
    }
}

【讨论】:

  • 嘿 Micah,我同意你的观点,因为我也看到了 github 问题 3070 ,但你不能将MyDbContext 直接注入到你的Configure() 方法中吗?跨度>
  • 我相信我只是从那个 GitHub 问题中复制了这个。可能有更好的方法,但我认为该方法的作者(作为 EF 开发人员)知道什么是最好的,所以我只是复制了他们的解决方案。配置是在初始化 DI 之前还是之后运行?也许您从serviceScopeFactory 获得的 dbContext 与您从 DI 获得的有所不同?如果您找到比这更好的解决方案,请随时在此处提交编辑或评论。 :)
  • 只是检查一下,我还声称对这个话题一无所知 :) 我至少在两个地方回答了 (example) 断言直接进入 Configure() 的 DI 是 intro docs 的方式,也许有人会告诉我为什么我错了,或者他们有什么不同。谢谢,
  • 我不知道这是否适用于早期版本,对我来说它说 MyDbContext not found on DI 容器。我认为这是在 ConfigureServices 之前执行的,或者是并行执行的。
【解决方案2】:

我想知道你为什么要运行 EnsureCreated 作为服务的一部分。您真的希望您的网络服务器创建或更新数据库架构吗?如果数据库不是是最新的,为什么网络服务器会启动并服务请求?

您是否真的非常信任您的迁移,以至于它们在执行时不会破坏数据,以至于您不想在运行后测试数据?

此外,这将要求您授予网络服务器数据库用户更改数据库架构的权限。这本身就是一个漏洞 - 接管您的网络服务器的人将能够修改您的数据库架构。

我建议您在自己运行的小型实用程序中创建数据库并应用迁移,而不是作为 Web 应用程序的一部分。

【讨论】:

  • 我很欣赏您反对从应用程序中创建/迁移的论点。对于企业规模的应用程序,我倾向于在所有方面都同意你的看法。然而,对于一个小型启动服务,在应用程序内部创建/迁移极大地简化了部署、测试、迁移、管理、调试等,我相信在朝着 MVP 工作时额外的风险是值得的。一旦服务充分增长,就可以考虑提取数据库创建/迁移。
  • 在我的情况下,我的客户是基于 Linux 的程序员,他希望通过编辑配置文件来切换数据库服务器。他将处理克隆和那些。如果没有 EnsureCreated,他必须安装所有工具才能运行 Update-Database。
  • 有一个很好的 Migrate 实用程序可以做到这一点。
  • 这是在开发中使用内存数据库或测试时使用的完全有效的方法。
【解决方案3】:

我认为zmbq 的建议是正确的,并且有一种方法可以确保迁移与部署一起运行,以便使用 Visual Studio 的发布功能同步二进制文件和数据库更改。

针对 IIS 实例发布时,可以指定目标数据库连接字符串以用于同时运行所需的迁移:

这将确保仅在需要时应用更改(不是每次应用程序启动时),并且应用程序使用最少需要的数据库权限(即数据库写入器、读取器等)运行,而不是更改表、创建索引等权限.

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 2017-11-30
    • 2016-12-21
    • 2015-02-08
    相关资源
    最近更新 更多