Entity Framework Core Migrations on Linux

Run Entity Framework Core Database Migrations While Deploying to Linux

Posted on September 28, 2018

As you’ve probably heard, ASP.NET Core runs on Linux (and macOS)! And it’s actually pretty easy to get started. However, running Entity Framework Core database migrations on Linux after publishing is not as easy.

During development [on Linux and macOS], running migrations is as simple as always:

$ dotnet ef database update

Note that to use the dotnet ef command, you must either have version 2.1+ of the .NET Core SDK installed, or the Microsoft.EntityFrameworkCore.Tools NuGet package installed in your project.

~That’s because the EF tools are installed on your system and easily accessible. Where I ran into issues however, is while trying to deploy my application using AWS Code Deploy. Like most CI/CD systems, this is intended to be fully automated. Here are the high-level steps to deploy this application. I’ll cover the details of each step in a later blog post (or hopefully series). ~

  1. From your development machine or build server, publish your application and zip it up:
     $ dotnet publish -c Release
    
  2. Since Code Deploy relies on the above artifact being in an S3 bucket, put the file in the appropriate S3 bucket.

  3. Kick off the Code Deploy process. In my case, there’s a hook in the appspec.yml file to execute the migrations.

For example purposes, we’re going to assume my application was deployed to my Linux server at /var/www/html/api and this will be our working directory.

If we run the same database update command, we get an error:

$ dotnet ef database update
No project was found. Change the current working directory or use the --project option.

Well that’s interesting. I’d gladly specify a project file, but since the app has been published already, it doesn’t exist in our artifact. So now what? Turns out we need to be a little more verbose with our command:

# Note: I broke this up into lines to make it easier to read and explain

$ dotnet exec \
    --depsfile MyApiProject.deps.json \
    --runtimeconfig MyApiProject.runtimeconfig.json \
    
    "/opt/ef-tools/ef.dll" database update \
    --assembly MyApiProject.dll \
    --startup-assembly MyApiProject.dll \
    --root-namespace MyApiProject

When you run your EF commands from your development machine with the .csproj file, it gathers all the dependencies it needs from the project. Because we don’t have the .csproj file after publishing, we have to tell dotnet where to find those dependencies. Let’s take a look at these lines individually.

As a side note, if you want to see what dotnet is running when you run dotnet ef database update locally, you can add the --verbose flag. If there are migrations, you’ll have to scroll up and you’ll see a dotnet exec command similar to the above.

I’m really hoping the EF / .NET teams make this easier in the future. I’ve opened an issue here which talks about this, so please “up-vote” it if you’d like to see it as well. Also, a special thanks to Ben Day for his post and script pointing me in the right direction.

In the issue comment thread, the .NET CLI team does not recommend “trying this at home” [referring to running dotnet exec] - use caution with other use cases.