Azure DevOps, Scrum, & .NET Software Leadership and Consulting Services

Introducing Slide Speaker: Videos with Voice-over from your PowerPoint and Google Slides Presentations

Deploy Entity Framework Core Migrations from a DLL


[Updated 4/27/2018 — Added an EF Core 2 version of this script in a new blog post.]

[Updated 3/29/2017 — Added a bash version of this script for deploying EF Core Migrations from Linux.]

Entity Framework Migrations let you deploy incremental updates to a target database.  With Entity Framework Core (EF Core) this is done from the command line by going to the directory that contains your Entity Framework entity and migration code, compiling that code (dotnet build), and then calling “dotnet ef database update” to publish those changes to your target database.

This works great from a developer workstation or from a build server but it breaks down in the DevOps scenario where you want to deploy code that has already been built.  Put another way, you can easily do an EF Core migration deploy if you have the source code — but if you only have the compiled assemblies (DLLs), you’re mostly out of luck.

I ran into this one while trying to deploy a build using a TFS Release Management (RM) pipeline.  In RM, you take the output of a previous build, apply any configuration updates you need for your target environment, and then deploy the already built code into that environment.  This typically involves deploying not just the code but also any database updates.  And since you’re definitely NOT re-compiling that code — you’re deploying the already built DLLs — you slam face-first into this EF Core migration limitation.

The Solution

Based on a hint from Brice Lambson, I created a simple batch script (and bash shell script) that replicates what the “dotnet ef database update” command does under the surface.  This takes the published output of your EF Core project, wires up the arguments for the source files, and triggers the database update logic.

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%

The script assumes that it’s in the same directory as your published EF Core DLL.  When I say “published”, I mean that you’ve run “dotnet publish -o {path}” on your EF Core project to compile it and publish just the source files for that project.  So, copy the batch script into that published directory and then run the following command:

deploy-ef-migrations.bat {EfCoreRootNamespace}

The only arg that you need to supply for the Windows version is the root namespace for your EF Core code.  By default, this is the same name as the DLL minus the “.dll” extension.  For example, if my DLL is Benday.EfCore.Api.dll, then my call is

deploy-ef-migrations.bat Benday.EfCore.Api

For Linux, it’s the same except for the name of the script.  For example, if my DLL is Benday.EfCore.Api.dll, then my call is

./deploy-ef-migrations.sh Benday.EfCore.Api

Summary

My recommendation is that, if you’re doing EF Core migrations as part of a TFS Release Management pipeline, you should do a separate “dotnet publish” for your EF Core API project to a location in your drop directory and then copy deploy-ef-migrations.bat into that drop directory folder.  This will make deploying your migrations a lot easier to script out when you’re doing your RM release.

Here’s a link to that EF Core migration publish script for Windows.  Here’s a link to the EF Core migration publish Linux bash script.

I hope this helps.

-Ben

 

— Looking for help getting your Entity Framework code plugged into your DevOps pipelines? Need some assistance scripting your DevOps deploys for your applications?  Have you hit the wall on Entity Framework migrations and want to switch to SQL Server Data Tools projects?  We can help.  Drop us a line at info@benday.com

SUBSCRIBE TO THE BLOG


12 responses to “Deploy Entity Framework Core Migrations from a DLL”

  1. Dias Avatar
    Dias

    Ben could U provide the same solution for Net core 2 ???

  2. Serhii Prostakov Avatar
    Serhii Prostakov

    Same solution applies to net core 2.0, just make sure that you are referencing the right ef.dll, the 2.0 version in home nuget packages folder.

  3. Mateus Leonardi Avatar

    Hi Benjamin,

    I’m trying to run this command but I’m getting this error: A fatal error was encountered. The library ‘hostpolicy.dll’ required to execute the application was not found

    Do you know how to solve it?

    Thanks in advance.

    1. Ben Day Avatar

      Hey Mateus —

      I’m not sure where that hostpolicy.dll problem would be coming from. Can you give me a little more info?

      Also, FYI, I created a new EF Core 2 version of this deployment script. That might help you out.
      https://www.benday.com/2018/04/27/deploy-entity-framework-core-2-0-migrations-from-a-dll/

      -Ben

  4. […] a previous blog post, I discussed how difficult it is to deploy Entity Framework Core migrations from the compiled […]

  5. […] originally wrote a batch script for EF Core v1 and included it in a blog post and then updated it for EF Core 2.0. This script does almost exactly the same thing as what […]

  6. cortex93 Avatar
    cortex93

    Any solutions for full desktop target ? As the dotnet core runtime is not installed on the target machine, it is not possible to call dotnet exec. Note that I don’t want to embed Database.Migrate in the application and have a specific application flow for that. Do you know if a “migrate.exe” exist as a bootstrapping replacement of dotnet ef for full desktop ?

    1. Ben Day Avatar

      When you say “full desktop target” do you mean something like Windows Forms or WPF? In that case, you’d be probably using Entity Framework rather than Entity Framework Core, right? If you’re doing that, then migrate.exe is probably the right way to go. (https://docs.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/migrate-exe)

      I’m not 100% sure I understood your question so let me know if I’m suggesting something silly.

      -Ben

  7. cortex93 Avatar
    cortex93

    I mean target like net472 instead of netcoreapp. I saw that there is an equivalent to migrate.exe named ef.exe
    The issue is that currently it is embeded in a nuget package (Microsoft.EntityFrameworkCore.Tools) and it is not convenient to call it from a TFS release pipeline.
    The solution that seems to be commonly set up is to have a dedicated console app which call the migration bits and deploy it to the server.

  8. Oleksandr Martyniuk Avatar
    Oleksandr Martyniuk

    I also faced with a similar issue. In my case it was “Could not load file or assembly ‘Microsoft.Extensions.DependencyInjection.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60’. The system cannot find the file specified.” I think it is specific to a project.

    To fix the issue you need to add a new parameter into script: –runtimeconfig .\%EfMigrationsNamespace%.runtimeconfig.json

    For example for dotnet core 2.1:
    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\2.1.0\tools\netcoreapp2.0\any\ef.dll

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

  9. Oleksandr Martyniuk Avatar
    Oleksandr Martyniuk

    Ben, thank you for a job! It really has helped me in my work.

  10. Matthew Koch Avatar
    Matthew Koch

    Hi Ben, thank you! I know you have some newer articles about this but I don’t quite understand the recommendation for a separate “dotnet publish” – what is the benefit of doing that? What If I only have a single ASP.NET Core app and I want to have this batch script available in my drop folder for it to be run as a part of a Release, but not deployed along with the app?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.