Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does application start with dotnet ef migrations add?

I have strange behavior with EF Core tools in developer PowerShell in VS2019.

After creating migration with this command:

dotnet ef migrations add VisibleLink -p .\src\Only.Portal.Data\ -s .\src\Only.Portal.Web

And it is causing to start my app, but previously it didn't. The method to apply last migrations, which causes dotnet ef migrations remove fully broken, because when using it, it firstly starts an app and then calls `Migrate().

Then I am getting a message:

The migration '20220128090939_VisibleLink' has already been applied to the database. Revert it and try again. If the migration has been applied to other databases, consider reverting its changes using a new migration instead

Looks like dead end loop.

like image 761
hoozr Avatar asked Apr 08 '26 12:04

hoozr


1 Answers

I'm not satisfied with author's own answer marked as accepted solution. It's very unclear to me what the actual "solution" is here. It is only mentioned that one should "use Startup". No mention of the exact thing that actually resolves the issue.

I'm running a .NET 6 ASP.NET app with minimal API for startup, and ran into the same issue. dotnet ef migrations would call my startup code, causing the entire application to try to start up, and fail (specifically I had a service that ran directly at start, that tried to use a database table that I'm actively trying to create a migration for).

I solved it by stepping away from the minimal API and creating a Program class, with a "fake" public static IHostBuilder CreateHostBuilder method.

public class Program
{
    // Have a Main that actually runs/starts your app with all the logic
    public static async Task Main(string[] args)
    {
        // Here I do automatic migrations...
        // ...

        // Web app initialization logic
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddRazorPages();

        var app = builder.Build();

        app.UseAuthentication();
        app.UseAuthorization();
        app
            .MapControllers()
            .RequireAuthorization();
        // etc.

        await app.RunAsync();
    }
    
    // Have a CreateHostBuilder that simply returns a default builder.
    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        Console.WriteLine("Doing Entity Framework migrations stuff, not starting full application");
        return Host.CreateDefaultBuilder();
    }
}

EF will look for a CreateHostBuilder method in Program. If it finds it, it won't call Main, and basically skip the entire initialization of your webapp and return a very empty host builder, sufficient enough for EF to do its work.

This feels like a bit of a hack, and it might not work at a later date.

Better solution for EF Core 7.0+ users

If you're using EF Core 7.0 or higer, please see this answer. You can now return an empty host builder when EF.IsDesignTime is true:

// Program.cs

if (EF.IsDesignTime) {
    new HostBuilder().Build().Run();
    return;
}

// Normal startup
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();

var app = builder.Build();

app.UseAuthentication();
// ...
like image 135
René Sackers Avatar answered Apr 10 '26 00:04

René Sackers