intcreator
intcreator

Reputation: 4414

How do I resolve the service for a type during an Entity Framework Core database update?

I am attempting to initialize a PostgreSQL database by running existing database migrations for .fmbot. I made an MVCE for the purposes of this question but here's the GitHub repo for reference.

Here's my file structure:

FMBot.Bot and FMBot.Persistence.EntityFrameWork as two separate projects

Here is my stripped down class for handling database migrations in the FMBot.Persistence.EntityFrameWork project. This builds with only warnings and has no underlined errors in Visual Studio:

FMBotDbContext.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace FMBot.Persistence.EntityFrameWork
{
    public class FMBotDbContext : DbContext
    {
        private readonly IConfiguration _configuration;

        public FMBotDbContext(IConfiguration configuration)
        {
            Console.WriteLine("configuration is ", configuration);
            this._configuration = configuration;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseNpgsql(this._configuration["Database:ConnectionString"]);
            }
        }
    }
}

Here's the code in Startup.cs I expect would enable FMBotDbContext to be instantiated when needed.

Startup.cs

services.AddDbContextFactory<FMBotDbContext>(optionsBuilder =>
    optionsBuilder
        .UseNpgsql(this.Configuration["Database:ConnectionString"])
        .UseSnakeCaseNamingConvention()
    );

However if I comment out this code I get the same result when I run the update command below. I suspect I need to add more to Startup.cs but I have no idea what it would be.

I am using this command with the intent that it will run all the migrations and set up the database to be populated with data:

Update-Database -verbose -project FMBot.Persistence.EntityFrameWork -Startup FMBot.Bot -Context FMBotDbContext

However when I run this command I get the following error:

Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'FMBotDbContext'. 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.Extensions.Configuration.IConfiguration' while attempting to activate 'FMBot.Persistence.EntityFrameWork.FMBotDbContext'.

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.b__13()
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass21_4.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.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

I believe this is because something (that I can't see or edit but is triggered by the command?) is trying to call the FMBotDbContext constructor but is having issues with the type of the configuration object matching IConfiguration, but this is where I'm stuck.

I've spent two days trying to figure this out but I can't figure out what I'm doing wrong. I'm open to changing any stage of my approach. I'm new to .NET and Visual Studio with most of my experience being with Node if that helps you understand my thought process.

The project maintainer's solution to this problem is to paste in hardcoded configuration values when initializing the database, which I'm trying to avoid.

How to I resolve this error?

Upvotes: 1

Views: 522

Answers (1)

SBFrancies
SBFrancies

Reputation: 4250

Caveat, I haven't tested this, but I'd suggest the following steps:

  1. Remove the OnConfiguring(DbContextOptionsBuilder optionsBuilder) method from your FMBotDbContext class entirely.

  2. Remove the current constructor in the FMBotDbContext class and replace it with this:

public FMBotDbContext(DbContextOptions<FMBotDbContext> options)
    : base(options)
{
}
  1. If you want to use snake case change your Startup to configure it there.
services.AddDbContextFactory<FMBotDbContext>(b =>
            {
          b.UseNpgsql(this.Configuration["Database:ConnectionString"]);
          b.UseSnakeCaseNamingConvention();
            });

Upvotes: 1

Related Questions