Home > database >  Cannot instantiate implementation type Repository`1[TDBContext]' for service type 'IReposi
Cannot instantiate implementation type Repository`1[TDBContext]' for service type 'IReposi

Time:03-29

I'm hitting the error in the title when running this setup code:

Program.cs:

builder.Services.AddDbContext<TDBContext>(opt => opt.UseInMemoryDatabase("My"));

// Can't work out how to wire up the Repository?
//builder.Services.AddScoped<IRepository>(p => new TDBContext());
//builder.Services.AddScoped<IRepository, Repository>();
builder.Services.AddScoped(typeof(IRepository), typeof(Repository<>));
//builder.Services.AddScoped(typeof(IRepository), typeof(Repository<TDBContext>));

builder.Services.AddScoped<IMyService, MyService>();

var app = builder.Build();  //ERROR HERE!

Service and Repository:

public class MyService : IMyService
{
    private readonly IRepository _repository;
    
    public MyService(IRepository repository)
    {          
        _repository = repository;
    }
}
    
public class Repository<TDBContext> : IRepository where TDBContext : DbContext
{
    protected DbContext dbContext;

    public Repository(DbContext context)
    {
        dbContext = context;
    }
    public async Task<int> CreateAsync<T>(T entity) where T : class
    {
        this.dbContext.Set<T>().Add(entity);
        return await this.dbContext.SaveChangesAsync();
    }
    //.....
}


public class TDBContext : DbContext
{
    public TDBContext(DbContextOptions<TDBContext> options)
        : base(options)
    {
    }

    public virtual DbSet<MyTransaction> Transactions { get; set; } = null!;

    public TDBContext()
    {
    }
}

I've tried a few suggestions found on here shown as code comments but no luck. Can someone please clarify how I wire up the Repository and get the DI to load in the DbContext?

CodePudding user response:

Check the repository constructor. The container does not know how to handle DbContext as dependency when resolving the repository.

Did you mean to use the generic argument type instead?

Also the naming of the generic parameter might cause confusion.

public class Repository<TContext> : IRepository where TContext : DbContext {
    protected DbContext dbContext;

    public Repository(TContext context) {
        dbContext = context;
    }

    public async Task<int> CreateAsync<T>(T entity) where T : class {
        this.dbContext.Set<T>().Add(entity);
        return await this.dbContext.SaveChangesAsync();
    }

    //.....
}

And the registration will need to use the closed type

//...

builder.Services.AddScoped<IRepository, Repository<TDBContext>>();

//...
  • Related