Search code examples
c#dependency-injectionazure-functionsentity-framework-6dbcontext

Errror in FunctionStartup with Azure Functions .NET 6.0 EFCore Dependyinjection, IdentityDbContext


Unable to resolve service for type 'Microsoft.Azure.WebJobs.Script.IFileLoggingStatusManager' while attempting to activate 'Microsoft.Azure.WebJobs.Script.Diagnostics.HostFileLoggerProvider'.

DBContext.cs:

public class ApplicationDbContext : IdentityDbContext<User, Role, Guid, IdentityUserClaim<Guid>, UserRole, IdentityUserLogin<Guid>, IdentityRoleClaim<Guid>, IdentityUserToken<Guid>>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    { }
}

Dependencies:

<PackageReference Include="Flurl" Version="3.0.2" />
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.19.0" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.15.0" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.OpenApi" Version="1.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.ApplicationInsights" Version="2.19.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.10.0" />
<PackageReference Include="Azure.Storage.Common" Version="12.9.0" />
<PackageReference Include="Azure.Storage.Files.Shares" Version="12.8.0" />
<PackageReference Include="Azure.Storage.Queues" Version="12.8.0" />
<PackageReference Include="FluentValidation.AspNetCore" Version="10.3.4" />
<PackageReference Include="HtmlSanitizer" Version="6.0.453" />
<PackageReference Include="MediatR" Version="9.0.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="5.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Clients.ActiveDirectory" Version="5.2.9" />
<PackageReference Include="NetTopologySuite" Version="2.4.0" />
<PackageReference Include="Polly" Version="7.2.2" />
<PackageReference Include="ProjNet" Version="2.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">

Startup.cs:

[assembly: FunctionsStartup(typeof(Startup))]
namespace Technoleon.Api
{
    public class Startup : FunctionsStartup
    {
        public Startup() { }

        IConfiguration Configuration { get; set; }

        private static readonly RetryPolicy _retryPolicy = Policy.Handle<Exception>().WaitAndRetry(5, _ => TimeSpan.FromSeconds(5));

        public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
        {
            builder.ConfigurationBuilder
                   .AddJsonFile(Path.Combine(builder.GetContext().ApplicationRootPath, "appsettings.json"), optional: true, reloadOnChange: true).Build();
        }

        public override void Configure(IFunctionsHostBuilder builder)
        {
            Configuration = builder.GetContext().Configuration;
            ConfigureServices(builder.Services);

            var serviceProvider = builder.Services.BuildServiceProvider();

            using (var scope = serviceProvider.CreateScope())
            {
                var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                _retryPolicy.Execute(() => context.Database.EnsureCreated());
                _retryPolicy.Execute(() => context.Database.Migrate());

                var userManager = scope.ServiceProvider.GetService<UserManager<User>>();
                _retryPolicy.Execute(() => UserData.Seed(userManager));
            }
        }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton(this);

            services.AddDbContext<ApplicationDbContext>(options => SqlServerDbContextOptionsExtensions.UseSqlServer(options, Configuration.GetConnectionString("Technoleon"),
                sqlServerOptions => sqlServerOptions.EnableRetryOnFailure(5, TimeSpan.FromSeconds(5), null)
                .UseNetTopologySuite()
                .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)
            ));

            services.AddLogging(builder =>
            {
                builder.AddApplicationInsights();
                builder.AddFilter<ApplicationInsightsLoggerProvider>("", LogLevel.Trace);
            });

            #ConfigureOtherServices...
        }
    }
}

I have rebuilt my web app from .NET 5 to Azure Functions .NET 6.

I got an Azure Functions project in .NET 6.0 with EF Core and dependency injection. I am configuring my project in Startup.cs with FunctionsStartup.

When trying to configure my local SQL Server database, I get this error:

Unable to resolve service for type 'Microsoft.Azure.WebJobs.Script.IFileLoggingStatusManager' while attempting to activate 'Microsoft.Azure.WebJobs.Script.Diagnostics.HostFileLoggerProvider'.*

It crashes when I try to call:

var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

How can I solve this error?

Please let me know if you need some additional information.


Solution

  • Unfortunately this doesn't work. The services are not in a full 'workable' state while you are still inside the Configure method. Read the 'Caveats' here: https://learn.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection

    One workaround is to register a custom IWebJobStartup class in your function app, which gets called after successful initialization of the services. It's a safe place to get back the db context from services. This answer has a sample: https://stackoverflow.com/a/68207734/687190

    Another workaround is to apply your migrations in your pipeline, before you deploy your app (if you are using CI/CD). Here's a link how to do it with an older version, but the concept is the same. https://dibranmulder.github.io/2018/08/23/Azure-functions-V2-with-EF-Core/