Skip to content

System.InvalidOperationException: Unable to build IHost when creating EF Migration with Minimal API dotnet 6 #60891

Closed

Description

@IanBuck-dev

Description

I have an issue when creating ef migrations for the newest release candidate 6.0.0-rc.2.21480.5 for dotnet 6 with the minimal apis. It seems to be a similar issue as explained here dotnet/aspnetcore#33886

The timeout for creating a WebApplicationFactory at design time seems to be 5 sec and that is not enough for me when I add new migrations, because I need to setup a lot of configuration before. I get this exception when trying to run any command that requires the project to be build like dotnet ef migrations add AddedPlanningSessions -v and the DbContext to be fetched from the service provider. I would expect there to be no timeout at all or at least a very large one when using WebApplicationFactory at design time.

System.InvalidOperationException: Unable to build IHost
   at Microsoft.Extensions.Hosting.HostFactoryResolver.HostingListener.CreateHost()
   at Microsoft.Extensions.Hosting.HostFactoryResolver.<>c__DisplayClass8_0.<ResolveHostFactory>b__0(String[] args)
   at Microsoft.Extensions.Hosting.HostFactoryResolver.<>c__DisplayClass11_0.<ResolveServiceProviderFactory>b__3(String[] args)
   at Microsoft.EntityFrameworkCore.Design.Internal.AppServiceProviderFactory.CreateFromHosting(String[] args)

The issue can be easily reproduced by creating an empty project with minimal api dotnet new web -o service, adding a dbcontext to the DI and adding a sleep of 6 sec.

Include your code

using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDbContext<ApplicationDbContext>(
    options => options.UseSqlServer("localhost"));

Thread.Sleep(TimeSpan.FromSeconds(6));

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

Include verbose output

Output when building my project where the steps until builder.Build() take too long.

dotnet exec --depsfile /Users/ian/Repos/work/planner-service/service/bin/Debug/net6.0/service.deps.json --additionalprobingpath /Users/ian/.nuget/packages --additionalprobingpath /usr/local/share/dotnet/sdk/NuGetFallbackFolder --runtimeconfig /Users/ian/Repos/work/planner-service/service/bin/Debug/net6.0/service.runtimeconfig.json /Users/ian/.dotnet/tools/.store/dotnet-ef/6.0.0-rc.2.21480.5/dotnet-ef/6.0.0-rc.2.21480.5/tools/netcoreapp3.1/any/tools/netcoreapp2.0/any/ef.dll dbcontext info --assembly /Users/ian/Repos/work/planner-service/service/bin/Debug/net6.0/service.dll --project /Users/ian/Repos/work/planner-service/service/service.csproj --startup-assembly /Users/ian/Repos/work/planner-service/service/bin/Debug/net6.0/service.dll --startup-project /Users/ian/Repos/work/planner-service/service/service.csproj --project-dir /Users/ian/Repos/work/planner-service/service/ --root-namespace PlannerService --language C# --framework net6.0 --nullable --working-dir /Users/ian/Repos/work/planner-service/service --verbose
Using assembly 'service'.
Using startup assembly 'service'.
Using application base '/Users/ian/Repos/work/planner-service/service/bin/Debug/net6.0'.
Using working directory '/Users/ian/Repos/work/planner-service/service'.
Using root namespace 'PlannerService'.
Using project directory '/Users/ian/Repos/work/planner-service/service/'.
Remaining arguments: .
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'service'...
Finding Microsoft.Extensions.Hosting service provider...
Using environment 'Development'.
Loading config from: global, planner-service.
System.InvalidOperationException: Unable to build IHost
   at Microsoft.Extensions.Hosting.HostFactoryResolver.HostingListener.CreateHost()
   at Microsoft.Extensions.Hosting.HostFactoryResolver.<>c__DisplayClass8_0.<ResolveHostFactory>b__0(String[] args)
   at Microsoft.Extensions.Hosting.HostFactoryResolver.<>c__DisplayClass11_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: Unable to build IHost
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'PlannerContext'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'PlannerContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
 ---> System.InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[PlannerService.DAL.PlannerContext]' while attempting to activate 'PlannerService.DAL.PlannerContext'.
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance(IServiceProvider provider, Type type)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass21_4.<FindContextTypes>b__13()
   --- End of inner exception stack trace ---
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass21_4.<FindContextTypes>b__13()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.GetContextInfo(String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.GetContextInfoImpl(String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.GetContextInfo.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Unable to create an object of type 'PlannerContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

Include provider and version information

EF Core version: 6.0.0-rc.2.21480.5
Database provider: Microsoft.EntityFrameworkCore.SqlServer 6.0.0-rc.2.21480.5
Target framework: NET 6.0
Operating system:
IDE: VS Code Version: 1.61.1

Activity

  1. ajcvickers commented on Oct 22, 2021

    @ajcvickers
    Contributor
  2. davidfowl commented on Oct 22, 2021

    @davidfowl
    Member

    This is a tough one as we need to tradeoff how much is too much time before we give up waiting for the host builder to be created... It's possible we need an environment variable override for these cases.

    @ajcvickers Do you have a preference for where this gets fixed? I think we'd add support for an environment variable to override the timeout for cases like this. EF can provide a different timeout here

    cc @maryamariyan @eerhardt

  3. ajcvickers commented on Oct 22, 2021

    @ajcvickers
    Contributor

    @davidfowl I don't have strong preferences. If you provide the mechanism, we can make use of it.

  4. davidfowl commented on Oct 22, 2021

    @davidfowl
    Member

    https://github.com/dotnet/efcore/blob/8144d50ec0d15b87c35a9a3a425b1faadafb87f1/src/EFCore.Design/Design/Internal/AppServiceProviderFactory.cs#L53

    I can think of 2 things:

    • Make the default infinite for the EF tools, if it hangs then you can write out a message saying it should control+C (this is if somebody runs the tool on an app that is on .NET 6 but doesn't use the host at all). Treat it like an edge case.
    • Have an environment variable that the user can set.
  5. eerhardt commented on Oct 22, 2021

    @eerhardt
    Member

    Is 5 seconds a reasonable default? Seems pretty low to me

  6. davidfowl commented on Oct 22, 2021

    @davidfowl
    Member

    Yea, maybe it's too small. What should the default be?

  7. ajcvickers commented on Oct 23, 2021

    @ajcvickers
    Contributor

    What are the scenarios in which we expect this to timeout? I assume that it is when the application does not actually use hosting, right? But then, more specifically for EF, the question is whether or not we have to wait for the timeout if the EF model is discovered in some other way. For example, do we have to wait for the timeout if:

    • There is a DbContext with a parameterless constructor that we can use?
    • There is a DbContextFactory?

    I think if those two cases work without waiting for the timeout, then having a longer timeout is okay, because we will only cause slowness in real negative cases where we are going to show an error anyway.

    It seems like we need to do some investigation here into the user experience.

    /cc @bricelam

  8. davidfowl commented on Oct 23, 2021

    @davidfowl
    Member

    The timeout is only there for this edge case:

    The user runs the EF tool on a .NET 6.0 application that references hosting but doesn't use it in the main entry point. Maybe its ok hanging in this scenario with a message on what the user can do?

  9. ajcvickers commented on Oct 25, 2021

    @ajcvickers
    Contributor

    @davidfowl In that case, it seems like you can just increase the timeout significantly. If all context discovery fails, then we will output:

    Unable to create an object of type 'PlannerContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

    As shown above.

  10. davidfowl commented on Oct 26, 2021

    @davidfowl
    Member

    Right but it wouldn't show that message. It would just hang forever unless other changes were made to show the message after some timeout

  11. ajcvickers commented on Oct 26, 2021

    @ajcvickers
    Contributor

    @davidfowl I don't mean make the timeout infinite. I just mean increase it significantly, to say 20 or 30 seconds. It will then timeout and show the message. The user can then implement a design time context factory, in which case they can hopefully resolve the EF model quicker, or, at least, let it take as long as necessary without any timeout.

  12. davidfowl commented on Oct 26, 2021

    @davidfowl
    Member

    Lets do that then. @eerhardt We should also change the default in the HostFactoryResolver as well (even though it's shared source).

  13. davidfowl commented on Oct 26, 2021

    @davidfowl
    Member
  14. eerhardt commented on Oct 26, 2021

    @eerhardt
    Member

    Should this issue get moved to dotnet/runtime then? Or is there a change EF should make here as well?

  15. ajcvickers commented on Oct 26, 2021

    @ajcvickers
    Contributor

    @eerhardt As far as I know, it should move to runtime. EF will pick up the new source from there.

  16. 5 remaining items

  17. removed
    untriagedNew issue has not been triaged by the area owner
    on Oct 28, 2021
  18. added this to the 7.0.0 milestone on Oct 28, 2021
  19. added
    enhancementProduct code improvement that does NOT require public API changes/additions
    on Oct 28, 2021
  20. maryamariyan commented on Oct 28, 2021

    @maryamariyan
    Contributor

    Next to do here based on earlier conversation

    I just mean increase it significantly, to say 20 or 30 seconds.

    is to increase timeout. On top of that we could consider adding an environment variable that could help developers set custom timeout

  21. davidfowl commented on Nov 11, 2021

    @davidfowl
    Member

    @ghorsey-opt this won't help but you can remove ConfigureAppConfiguration and just use builder.Configuration to clean up the code a bit

  22. davidfowl commented on Nov 11, 2021

    @davidfowl
    Member

    We're gonna fix the bug in a 6.0.x patch.

  23. modified the milestones: 7.0.0, 6.0.x on Nov 12, 2021
  24. halter73 commented on Nov 15, 2021

    @halter73
    Member

    I think the main thing we need to do is improve the exception message. System.InvalidOperationException: Unable to build IHost does not make it clear there was a 5 second timeout waiting for Program.Main() to actually build the IHost. Adding remediation options to the exception message like setting a new environment variable to increase the timeout will help a lot.

    I'm not sure most users want to wait 20-30 seconds to load the IHost for EF migrations. I get that's the max before it times out, but it would be nice to let developers know that reducing the time spent in Program.Main() before building the IHost will speed up migrations rather than leave people to wonder why migrations are now slower.

    Maybe we could consider adding a command line argument to indicate that it's being resolved by the HostFactoryResolver so developers can short-circuit unnecessary startup logic when just setting up DB services for doing migrations. We already add --applicationName, so maybe the exception message could reference that.

  25. ghost added
    in-prThere is an active PR which will close this issue when it is merged
    on Nov 16, 2021
  26. ghost removed
    in-prThere is an active PR which will close this issue when it is merged
    on Nov 17, 2021
  27. ghost locked as resolved and limited conversation to collaborators on Dec 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-Extensions-HostingenhancementProduct code improvement that does NOT require public API changes/additions

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions