Search code examples
c#.net-coreentity-framework-coredatabase-migration

Unable to create a 'DbContext' of type ''. The exception 'Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Comm


I'm following a video on GraphQL (min 1.28.22), and when I run the command "dotnet ef migrations add AddPlatformToDb", it returns the following issue:

Unable to create a 'DbContext' of type ''. The exception 'Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[CommanderGQL.Data.AppDbContext]' while attempting to activate 'CommanderGQL.Data.AppDbContext'.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

Despite writing the same things, it doesn't create any issues in the video.

CommanderGQL.csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="GraphQL.Server.Ui.Voyager" Version="7.7.1" />
    <PackageReference Include="HotChocolate.AspNetCore" Version="13.9.0" />
    <PackageReference Include="HotChocolate.Data.Entityframework" Version="13.9.0" />
    <PackageReference Include="Microsoft.EntityframeworkCore.Design" Version="8.0.2">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityframeworkCore.SqlServer" Version="8.0.2" />
  </ItemGroup>

</Project>

docker-compose.yaml:

version: '3'
services:
  sqlserver:
    image: "mcr.microsoft.com/mssql/server:2017-latest"
    environment:
      ACCEPT_EULA: "Y"
      SA_PASSWORD: "pa55w0rd!"
      MSSQL_PID: "Express"
    ports:
      - "1433:1433"

appsettings.Development.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "CommandConStr" : "Server=localhost,1433;Database=CommandsDB;User Id=sa;Password=pa55w0rd!"
  }
}

appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*"
}

Startup.cs:

using CommanderGQL.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

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

        //public IConfiguration Configuration { get; }
        private readonly IConfiguration Configuration;

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<AppDbContext>(opt => opt.UseSqlServer
            (Configuration.GetConnectionString("CommandConStr")));
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // Configure production environment here
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                // Configure endpoints here
            });
        }
    }
}

Platform.cs:

using System.ComponentModel.DataAnnotations;

namespace CommanderGQL.Models
{
    public class Platform
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public string LicenseKey { get; set; }
    }
}

AppDbContext.cs:

using CommanderGQL.Models;
using Microsoft.EntityFrameworkCore;

namespace CommanderGQL.Data
{
    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {
        }

        public DbSet<Platform> Platforms { get; set; }
    }
}

Program.cs:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

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

app.Run();

Solution

  • You have created an application using "new" (since .NET 6) minimal hosting model (which is used since .NET 6 templates). You basically have 2 options:

    1. Remove the Startup.cs and move it contents to Program.cs file, everything from ConfigureServices should be called on builder.Services (instead of services), and everything from Configure should be called on app (possibly some modifications should me made):

      builder.Services.AddDbContext<AppDbContext>(opt => opt.UseSqlServer
               (builder.Configuration.GetConnectionString("CommandConStr")));
      // ...
      app.UseDeveloperExceptionPage(); 
      
    2. Rewrite your app and switch back to the generic hosting which can use the Startup

    Without this changes your code in Startup is not applied, so the context is not set up correctly for migrations.

    See also: