Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 391
Akshay Khot Avatar asked Dec 17 '20 09:12

Akshay Khot


People also ask

What is dbContextOptions?

The dbContextOptions carries the configuration information needed to configure the DbContext. The dbContextOptions can also be configured using the OnConfiguring method. This method gets the DbContextOptionsBuilder as its argument. It is then used to create the dbContextOptions.

What is Microsoft EntityFrameworkCore tools for?

The Entity Framework Core tools help with design-time development tasks. They're primarily used to manage Migrations and to scaffold a DbContext and entity types by reverse engineering the schema of a database.

Can I use EF core in .NET framework?

You can use EF Core in APIs and applications that require the full . NET Framework, as well as those that target only the cross-platform .

Can we configure the provider we are using in dbcontext?

As you can see we can also configure options such as which provider we are using… but we don’t have to do this here, we can defer this to the OnConfiguring method in our DbContext class if we wish. You might also be interested in...

How to add dbcontextoptions to base class?

In Startup.cs (Configure Services) public void ConfigureServices (IServiceCollection services) { //Some Code services.AddDbContext<LibraryContext> (); //Some Code } and then in your DbContext class instead on passing the DbContextOptions to your base class, configure them as follows.

What is a scoped service in efcontext?

The code above will register EFContext as a scoped service which means it is tied to the request which is ideal in a web application. As you can see we can also configure options such as which provider we are using… but we don’t have to do this here, we can defer this to the OnConfiguring method in our DbContext class if we wish.

Why is MVC throwing an exception when trying to create efcontext?

MVC is throwing the exception as it cannot find what class implements EFContext when it is attempting to create an instance of the CustomersController class.


2 Answers

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

like image 200
Rob Bowman Avatar answered Oct 21 '22 23:10

Rob Bowman


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>());
}
like image 7
Akshay Khot Avatar answered Oct 21 '22 23:10

Akshay Khot