dotnet/Scaffolding

Error when scaffolding endpoints with database context placed in a separate project

suugbut opened this issue · 3 comments

My repo at https://github.com/suugbut/CodegenBug provides some batch files to generate the solution and many more. Here I just pasted the problem description from it.


To illustrate the problem, I make 4 projects as follows:

  • Model project with one entity model User.cs

    public class User
    {
        public int Id { get; set; }
        public string Name { get; set; } = default!;
    }
  • Context project with one database context AppDbContext.cs

    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
        public DbSet<User> Users => Set<User>();
    }
  • MigrationForSqlite project with a trivial class Empty.cs

    public class Empty { }

    This project is used to keep migration files generated by ef tool for specific db provider (in this case for sqlite).

  • Api project with Program.cs

    var builder = WebApplication.CreateBuilder(args);
    
    
    builder.Services.AddDbContext<Context.AppDbContext>(dcob =>
    {
        dcob.UseSqlite("DataSource=Test.db", 
            sdcob => sdcob.MigrationsAssembly("MigrationForSqlite"));
    });
    
    
    var app = builder.Build();
    
    app.MapGet("/", () => "Hello World");
    
    app.Run();

I successfully did the following:

  • migration: dotnet ef migrations add Initializaiton -s Api -p MigrationForSqlite
  • applying migration: dotnet ef database update -s Api
  • running api server: dotnet run --project Api --launch-profile https
  • testing endpoint by navigating to https://localhost:7255 that produces Hello World

After shutting the server down, I attempted to scaffold endpoints for User model with the following batch file but I failed.

dotnet aspnet-codegenerator minimalapi ^
-p Api ^
-e UserEndpoints ^
-m Model.User ^
-dc Context.AppDbContext ^
-outDir Endpoints ^
-dbProvider sqlite

The error messages are:

Building project ...
Finding the generator 'minimalapi'...
Running the generator 'minimalapi'...

Minimal hosting scenario!
Attempting to figure out the EntityFramework metadata for the model and DbContext: 'User'
Unable to create a 'DbContext' of type 'Context.AppDbContext'. The exception 'Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[ContUnable to create a 'DbContext' of type 'Context.AppDbContext'. The exception 'Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Context.AppDbContext]' while attempting to activate 'Context.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 StackTrace:
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.DbContextActivator.CreateInstance(Type contextType, Assembly startupAssembly, IOperationReportHandler reportHandler, String[] args)
   at Microsoft.EntityFrameworkCore.Design.DbContextActivator.CreateInstance(Type contextType, Assembly startupAssembly, IOperationReportHandler reportHandler)
   at Microsoft.VisualStudio.Web.CodeGeneration.EntityFrameworkCore.EntityFrameworkModelProcessor.TryCreateContextUsingAppCode(Type dbContextType, Type startupType)

Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Context.AppDbContext]' while attempting to activate 'Context.AppDbContext'. StackTrace:
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.CreateInstance(IServiceProvider provider, Type instanceType, Object[] parameters)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass20_5.<FindContextTypes>b__13()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)

Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Context.AppDbContext]' while attempting to activate 'Context.AppDbContext'.
   at Microsoft.VisualStudio.Web.CodeGeneration.ActionInvoker.<BuildCommandLine>b__6_0()
   at Microsoft.Extensions.CommandLineUtils.CommandLineApplication.Execute(String[] args)
   at Microsoft.VisualStudio.Web.CodeGeneration.ActionInvoker.Execute(String[] args)
   at Microsoft.VisualStudio.Web.CodeGeneration.CodeGenCommand.Execute(String[] args)
RunTime 00:00:20.53

hmmm thanks for reporting this issue, will take a look soon

@suugbut
I have same issue and resolved by following instructions from
https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli
Below is my example.

public class AppDbContextContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
    public AppDbContext CreateDbContext(string[] args)
    {
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();
        var connectionString = configuration.GetConnectionString("DefaultConnection");
        var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
        optionsBuilder.UseNpgsql(connectionString);
        return new AppDbContext(optionsBuilder.Options);
    }
}

@sunkeun-choi

@suugbut I have same issue and resolved by following instructions from https://learn.microsoft.com/en-us/ef/core/cli/dbcontext-creation?tabs=dotnet-core-cli Below is my example.

public class AppDbContextContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
    public AppDbContext CreateDbContext(string[] args)
    {
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .Build();
        var connectionString = configuration.GetConnectionString("DefaultConnection");
        var optionsBuilder = new DbContextOptionsBuilder<AppDbContext>();
        optionsBuilder.UseNpgsql(connectionString);
        return new AppDbContext(optionsBuilder.Options);
    }
}

In which project did you put this? I have 4 projects. Have you tested? We are talking the same scenario or not?