简体   繁体   中英

Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions'

I am trying to access the databse using EF Core 5.0 on an ASP.NET Core project. For the first migration, I overrode the OnConfiguring() method on the DBContext and updated the database successfully.

For the second migration, I decided to use the dependency injection in ASP.NET Core following the guidelines . Here are the changes I made.

  1. Added services.AddDbContext in my Startup.cs .
  2. Removed the OnConfiguring() method from DBContext .

After running dotnet ef migrations add Posts , I get following error:

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

If I add the --verbose flag, I get this output:

Build started...
dotnet build blog/app/app.csproj /verbosity:quiet /nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.50
Build succeeded.

Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider in assembly 'app'...
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...
Found DbContext 'BlogContext'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'BlogContext'. 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[app.Data.BlogContext]' while attempting to activate 'app.Data.BlogContext'.
   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__DisplayClass13_4.<FindContextTypes>b__13()
   
Unable to create an object of type 'BlogContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
 

However, the code works as expected when I run the web application, as in the BlogContext is created and injected into my classes by the DI layer, and I can access the database.

Hence, I am guessing the DI layer is not running as expected when running the dotnet ef migrations add command.

Here's my code.

// Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        IHostBuilder builder = Host.CreateDefaultBuilder(args)
                                        .UseSerilog()
                                        .ConfigureWebHostDefaults(webBuilder =>
                                        {
                                            webBuilder.UseStartup<Startup>();
                                        });

        IHost host = builder.Build();

        host.Run();
    }
}

// BlogContext

using app.Models;
using Microsoft.EntityFrameworkCore;

namespace app.Data
{
    public class BlogContext : DbContext
    {
        public DbSet<Post> Posts { get; set; }

        public DbSet<Comment> Comments { get; set; }

        public BlogContext(DbContextOptions<BlogContext> options) : base(options)
        {

        }
    }
}

// Startup.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public Startup(IConfiguration configuration)
    {
         Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public string ConnectionString => Configuration.GetConnectionString("Blog");

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<BlogContext>(opt => { opt.UseSqlite(ConnectionString); });
    }
}

Both the Startup and BlogContext live in the same project.

Thanks to Ivan and Kirk's comments above and reading the entire verbose output, I figured out the problem. Turned out I was not following the correct pattern in Program.cs .

From the documentation ,

The tools first try to obtain the service provider by invoking Program.CreateHostBuilder(), calling Build(), then accessing the Services property.

I had refactored the original Program.cs by moving CreateHostBuilder() inside main() , which broke the ef-core migration.

After modifying the Program.cs to following it works as expected.

public class Program
{
    public static void Main(string[] args)
        => CreateHostBuilder(args).Build().Run();

    // EF Core uses this method at design time to access the DbContext
    public static IHostBuilder CreateHostBuilder(string[] args)
        => Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(
                webBuilder => webBuilder.UseStartup<Startup>());
}

In my experience, better to create a class (in the same project as the context) that implements IDesignTimeDbContextFactory - as described here . That way, there's not guessing as to which code will get used when using the design time tools such as update-database

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM