在 Heroku 中运行 EF Core 迁移

Jav*_*ano 3 c# entity-framework heroku

我目前正在 .NET Core 中开发原型,为了简单起见,我使用了 Docker/Heroku。

我注意到的是,当尝试通过 运行迁移时heroku dotnet run ef database updatedotnetCLI 不可用。我很快注意到这是因为我的最终映像只有运行时,而不是 sdk。我的问题是:为了能够运行迁移,同时拥有仅运行运行时的较轻映像,什么最有意义?我是否因为只有运行时而大做文章?

这就是我当前的图像,以便能够像我现在一样运行迁移:

FROM mcr.microsoft.com/dotnet/core/sdk:3.0
WORKDIR /app
COPY --from=build-env /app/out ./

RUN dotnet tool install --global dotnet-ef

# Set ASPNETCORE_URLS to run the app on the port Heroku exposes.
# Kestrel run by default on 5000/1 and Heroku doesn't allow that.
CMD ASPNETCORE_URLS=http://*:$PORT dotnet Lazarus.dll
Run Code Online (Sandbox Code Playgroud)

我有 SDK 并且必须在生产映像中安装 EF CLI 感觉不对,所以欢迎任何见解!

Jav*_*ano 5

在尝试了不同的选项之后,最简单/最简单的方法是在实际应用程序代码中在应用程序启动之前运行迁移,挂钩到 webhost。

通过创建扩展函数,例如:

public static IWebHost MigrateDatabase<T>(this IWebHost webHost) where T : DbContext
{
    using(var scope = webHost.Services.CreateScope())
    {
        var services = scope.ServiceProvider;
        try
        {
            var db = services.GetRequiredService<T>();
            db.Database.Migrate();
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred while migrating the database.");
        }
    }
    return webHost;
}
Run Code Online (Sandbox Code Playgroud)

它可以在主入口点使用,如下所示:

public static void Main(string[] args)
{
    CreateWebHostBuilder(args)
        .Build()
        .MigrateDatabase<DatabaseContext>()
        .Run();
}
Run Code Online (Sandbox Code Playgroud)

虽然它不会将迁移作为部署过程的一部分运行,但作为启动过程的一部分,我觉得它更容易并且需要更少的移动部件才能开始。这也允许传送一个更小的图像,它只包含运行时而不是 SDK 以及所有工具。