`dotnet-ef migrations add` starts entire application when CreateHostBuilder method is not present
See original GitHub issueTLTR
When public static IHostBuilder CreateHostBuilder(string[] args) method is removed from Program.cs in a web api template project with dependencies on EF 6, generating migration with dotnet ef CLI tool starts the entire application instead of generating migration. In EF 5 this behaviour was not present.
Hello,
I’ve encountered strange behaviour of the dotnet ef CLI tool after updating my application to EF 6. Program.cs in our microservices looks like this:
public class Program
{
public static Task Main(string[] args) => WebHostHelper.BuildAndRunWebHostAsync<Startup>(args, validateDiConfigurationInDebug: true);
}
As you can see it lacks CreateHostBuilder(string[] args) because it wouldn’t be productive to add this method in all microservices. Instead, we provide a helper method as above. Also, what is important, our application is implementing IDesignTimeDbContextFactory in order to control creating of DbContext when migrations are being added (find simple reproduction here: https://github.com/marekott/dotnet-ef-add-migration-bug-reproduction). When application had dependency on EF 5 dotnet-ef migrations add Initial -v command produced valid migration (logs below). After updating to EF 6 the same command starts the entire application (logs below) that needs to be killed in order to finish producing migration (which in the end is a valid one). Adding CreateHostBuilder(string[] args) resolves this issue, application is not started and migration is generated. However, adding this method especially that it is not used and wasn’t needed for 3 years seem as a lazy solution.
Taking everything into consideration what is a reason for this strange behaviour? It seems like a bug, especially that it has worked previously.
Logs for EF 5
PS C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi> dotnet-ef migrations add Initial
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
PS C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi> dotnet-ef migrations add Initial -v
Using project 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj'.
Using startup project 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj'.
Writing 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\obj\SampleWebApi.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\marek.ott\AppData\Local\Temp\tmp277A.tmp /verbosity:quiet /nologo C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj
Writing 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\obj\SampleWebApi.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\marek.ott\AppData\Local\Temp\tmp2A4A.tmp /verbosity:quiet /nologo C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj
Build started...
dotnet build C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj /verbosity:quiet /nologo
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.28
Build succeeded.
dotnet exec --depsfile C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.deps.json --additionalprobingpath C:\Users\marek.ott\.nuget\packages --runtimeconfig C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.runtimeconfig.json C:\Users\marek.ott\.dotnet\tools\.store\dotnet-ef\6.0.5\dotnet-ef\6.0.5\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll migrations add Initial --assembly C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.dll --project C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj --startup-assembly C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.dll --startup-project C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj --project-dir C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\ --root-namespace SampleWebApi --language C# --framework net6.0 --working-dir C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi --verbose
Using assembly 'SampleWebApi'.
Using startup assembly 'SampleWebApi'.
Using application base 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0'.
Using working directory 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi'.
Using root namespace 'SampleWebApi'.
Using project directory 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Found IDesignTimeDbContextFactory implementation 'PostgresDbContextMigrationsFactory'.
Found DbContext 'SampleWebApiContext'.
Finding application service provider in assembly 'SampleWebApi'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Using DbContext factory 'PostgresDbContextMigrationsFactory'.
Using context 'SampleWebApiContext'.
Finding design-time services for provider 'Npgsql.EntityFrameworkCore.PostgreSQL'...
Using design-time services from provider 'Npgsql.EntityFrameworkCore.PostgreSQL'.
Finding design-time services referenced by assembly 'SampleWebApi'...
Finding design-time services referenced by assembly 'SampleWebApi'...
No referenced design-time services were found.
Finding IDesignTimeServices implementations in assembly 'SampleWebApi'...
No design-time services were found.
DetectChanges starting for 'SampleWebApiContext'.
DetectChanges completed for 'SampleWebApiContext'.
Writing migration to 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\Migrations\20220526065812_Initial.cs'.
Writing model snapshot to 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\Migrations\SampleWebApiContextModelSnapshot.cs'.
'SampleWebApiContext' disposed.
Done. To undo this action, use 'ef migrations remove'
Logs for EF 6
dotnet-ef migrations add Initial -v
Using project 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj'.
Using startup project 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj'.
Writing 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\obj\SampleWebApi.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\marek.ott\AppData\Local\Temp\tmp423C.tmp /verbosity:quiet /nologo C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj
Writing 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\obj\SampleWebApi.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\marek.ott\AppData\Local\Temp\tmp4460.tmp /verbosity:quiet /nologo C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj
Build started...
dotnet build C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj /verbosity:quiet /nologo
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:01.60
Build succeeded.
dotnet exec --depsfile C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.deps.json --additionalprobingpath C:\Users\marek.ott\.nuget\packages --runtimeconfig C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.runtimeconfig.json C:\Users\marek.ott\.dotnet\tools\.store\dotnet-ef\6.0.5\dotnet-ef\6.0.5\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll migrations add Initial --assembly C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.dll --project C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj --startup-assembly C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0\SampleWebApi.dll --startup-project C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\SampleWebApi.csproj --project-dir C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\ --root-namespace SampleWebApi --language C# --framework net6.0 --working-dir C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi --verbose
Using assembly 'SampleWebApi'.
Using startup assembly 'SampleWebApi'.
Using application base 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\bin\Debug\net6.0'.
Using working directory 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi'.
Using root namespace 'SampleWebApi'.
Using project directory 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Found IDesignTimeDbContextFactory implementation 'PostgresDbContextMigrationsFactory'.
Found DbContext 'SampleWebApiContext'.
Finding application service provider in assembly 'SampleWebApi'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Hosting environment: Development
Content root path: C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi
Now listening on: http://localhost:5000
Now listening on: https://localhost:5001
Application started. Press Ctrl+C to shut down.
Application is shutting down...
PS C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi> System.InvalidOperationException: The entry point exited without ever building an IHost.
at Microsoft.Extensions.Hosting.HostFactoryResolver.HostingListener.CreateHost()
at Microsoft.Extensions.Hosting.HostFactoryResolver.<>c__DisplayClass10_0.<ResolveHostFactory>b__0(String[] args)
at Microsoft.Extensions.Hosting.HostFactoryResolver.<>c__DisplayClass13_0.<ResolveServiceProviderFactory>b__3(String[] args)
at Microsoft.EntityFrameworkCore.Design.Internal.AppServiceProviderFactory.CreateFromHosting(String[] args)
An error occurred while accessing the Microsoft.Extensions.Hosting services. Continuing without the application service provider. Error: The entry point exited without ever building an IHost.
No application service provider was found.
Finding DbContext classes in the project...
Using DbContext factory 'PostgresDbContextMigrationsFactory'.
Using context 'SampleWebApiContext'.
Finding design-time services referenced by assembly 'SampleWebApi'...
Finding design-time services referenced by assembly 'SampleWebApi'...
No referenced design-time services were found.
Finding design-time services for provider 'Npgsql.EntityFrameworkCore.PostgreSQL'...
Using design-time services from provider 'Npgsql.EntityFrameworkCore.PostgreSQL'.
Finding IDesignTimeServices implementations in assembly 'SampleWebApi'...
No design-time services were found.
DetectChanges starting for 'SampleWebApiContext'.
DetectChanges completed for 'SampleWebApiContext'.
Writing migration to 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\Migrations\20220526070035_Initial.cs'.
Writing model snapshot to 'C:\Users\marek.ott\Desktop\demo\SampleWebApi\SampleWebApi\Migrations\SampleWebApiContextModelSnapshot.cs'.
'SampleWebApiContext' disposed.
Done. To undo this action, use 'ef migrations remove'
My dotnet ef version is:
Entity Framework Core .NET Command-line Tools
6.0.5
Issue Analytics
- State:
- Created a year ago
- Reactions:3
- Comments:14 (8 by maintainers)
Top Related StackOverflow Question
@davidfowl During application startup lot of things can be performed: microservice can send some message to the message bus indicating that it is started, it may register itself in Consul, some data seeding can take place. None of those is expected behavior when you are using EF tooling to generate new migration. Also application may require some mandatory configuration to be provided via env variables or Kubernetes mounted file (e.g. availability zone) without which it will throw, obviously you wouldn’t want to provide this configuration just to generate EF migration. Long story short it is not expected behavior that adding database migration will start your application, but if you don’t want to change existing behavior then at least add ability to directly specify in CLI
IDesignTimeDbContextFactory(as @plachor suggested) which we have implemented exactly for the reason of constructingDbContextfor the EF CLI tooling purpose.That: https://github.com/dotnet/efcore/issues/27322#issue-1119743287 would be best option for this case I believe. Since in docs you mentioned that:
Or allow to specify
IDesignTimeDbContextFactorytype explicitly indotnet efcommand instead ofcontext.