有沒有辦法從已發布的DLL運行EF Core RC2工具?

asp.net-core entity-framework-core

發布.Net Core RC1應用程序後,project.json中指定的命令具有為其創建的相應.cmd文件,這些文件可在部署後執行(例如web.cmd和ef.cmd)。在我的例子中,我想在我的部署目標上運行以下Entity Framework命令:

dotnet ef database update -c MyContext

當我從包含源代碼的文件夾運行它時,這工作正常,但是在發布後,它似乎沒有在編譯的DLL中找到命令。我對RC2命令變化的理解是“工具”可以編譯為名為dotnet - * .dll的獨立應用程序,可以通過CLI執行。如何將實體框架核心工具公開為已發布輸出中的可執行DLL?

僅供參考,我的構建/部署工作流程如下:

TeamCity的

dotnet restore => dotnet build => dotnet test => dotnet publish

八達通部署

上傳包=> EF更新數據庫=>等

一般承認的答案

我在項目中遇到了同樣的問題,但由於多種原因,我不希望遷移在應用程序啟動時自動運行。

為了解決這個問題,我更新了Program.cs以獲取兩個參數(完整代碼如下所示)

  • --ef-migrate ,以應用所有掛起的遷移,以及
  • --ef-migrate-check ,用於驗證是否已應用所有遷移

如果存在參數,則應用EF操作並退出程序,否則啟動Web應用程序。

請注意,它取決於Microsoft.Extensions.CommandLineUtils包以簡化命令行解析。

對於章魚部署,然後可以將包發布兩次到單獨的位置 - 一個用於運行遷移,另一個用於webhosting。在我們的例子中,我們添加了一個帶有內容的“post deploy powershell腳本”

$env:ASPNETCORE_ENVIRONMENT="#{Octopus.Environment.Name}"
dotnet example-app.dll --ef-migrate

在docker環境中,它也可以完美地工作

docker run -it "example-app-container" dotnet example-app.dll --ef-migrate

完整的Program.cs,不包括命名空間和使用:

//Remember to run: dotnet add package Microsoft.Extensions.CommandLineUtils
public class Program
{
    public static void Main(string[] args)
    {
        var commandLineApplication = new CommandLineApplication(false);
        var doMigrate = commandLineApplication.Option(
            "--ef-migrate",
            "Apply entity framework migrations and exit",
            CommandOptionType.NoValue);
        var verifyMigrate = commandLineApplication.Option(
            "--ef-migrate-check",
            "Check the status of entity framework migrations",
            CommandOptionType.NoValue);
        commandLineApplication.HelpOption("-? | -h | --help");
        commandLineApplication.OnExecute(() =>
        {
            ExecuteApp(args, doMigrate, verifyMigrate);
            return 0;
        });
        commandLineApplication.Execute(args);
    }

    private static void ExecuteApp(string[] args, CommandOption doMigrate, CommandOption verifyMigrate)
    {
        Console.WriteLine("Loading web host");
        var webHost = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        if (verifyMigrate.HasValue() && doMigrate.HasValue())
        {
            Console.WriteLine("ef-migrate and ef-migrate-check are mutually exclusive, select one, and try again");
            Environment.Exit(2);
        }

        if (verifyMigrate.HasValue())
        {
            Console.WriteLine("Validating status of Entity Framework migrations");
            using (var context = webHost.Services.GetService<DatabaseContext>())
            {
                var pendingMigrations = context.Database.GetPendingMigrations();
                var migrations = pendingMigrations as IList<string> ?? pendingMigrations.ToList();
                if (!migrations.Any())
                {
                    Console.WriteLine("No pending migratons");
                    Environment.Exit(0);
                }

                Console.WriteLine("Pending migratons {0}", migrations.Count());
                foreach (var migration in migrations)
                {
                    Console.WriteLine($"\t{migration}");
                }

                Environment.Exit(3);
            }
        }

        if (doMigrate.HasValue())
        {
            Console.WriteLine("Applyting Entity Framework migrations");
            using (var context = webHost.Services.GetService<DatabaseContext>())
            {
                context.Database.Migrate();
                Console.WriteLine("All done, closing app");
                Environment.Exit(0);
            }
        }

        // no flags provided, so just run the webhost
        webHost.Run();
    }
}

熱門答案

有一個解決這個問題的一個非常有用的帖子在這裡

它對我有用(我不得不稍微調整一下命令,但它給了我一個很好的基礎)。

總而言之:您可以通過傳遞ef.dll來複製dotnet ef database update命令(例如,直接從您的nuget文件夾(或者如果您沒有nuget,則從其他地方復制,因為您在prod機器上...))你的.dll包含一些附加參數的遷移(見下文)到dotnet.exe (或linux等價物)。

為了完整性,這裡是.cmd(也來自博客帖子!)

set EfMigrationsNamespace=%1
set EfMigrationsDllName=%1.dll
set EfMigrationsDllDepsJson=%1.deps.json
set DllDir=%cd%
set PathToNuGetPackages=%USERPROFILE%\.nuget\packages
set PathToEfDll=%PathToNuGetPackages%\microsoft.entityframeworkcore.tools.dotnet\1.0.0\tools\netcoreapp1.0\ef.dll

dotnet exec --depsfile .\%EfMigrationsDllDepsJson% --additionalprobingpath %PathToNuGetPackages% %PathToEfDll% database update --assembly .\%EfMigrationsDllName% --startup-assembly .\%EfMigrationsDllName% --project-dir . --content-root %DllDir% --data-dir %DllDir% --verbose --root-namespace %EfMigrationsNamespace%

(如果此cmd在博客帖子中,則為bash版本)

順便說一句。在許多github問題中也提到了這種方法: https//github.com/aspnet/EntityFramework.Docs/issues/328 https://github.com/aspnet/EntityFramework.Docs/issues/180

ps:我在Ben Day博客中找到了這個,所以歸功於Ben!



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因