I am Injecting GenericRepository into BL service that calles it in order to get data from entity framework. No Exception is thrown until I am trying to add the other BL Service as scoped I get the following Exception:
System.AggregateExceptionHResult=0x80131500 Message=Some services are not able to be constructed (Error while validating the service descriptor ‘ServiceType: BL.Interfaces.IDoorsBL Lifetime: Scoped ImplementationType: BL.Services.DoorsBL’: Unable to resolve service for type ‘Microsoft.EntityFrameworkCore.DbContext’ while attempting to activate ‘DAL.Repositories.GenericRepository[DAL.Models.Door]’.)
StackTrace:
at Microsoft.Extensions.DependencyInjection.ServiceProvider..ctor(ICollection`1
serviceDescriptors, ServiceProviderOptions options)
at Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(IServiceCollection services, ServiceProviderOptions options)
at Microsoft.Extensions.Hosting.Internal.ServiceFactoryAdapter`1.CreateServiceProvider(Object containerBuilder)
at Microsoft.Extensions.Hosting.HostBuilder.CreateServiceProvider()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at Microsoft.AspNetCore.Builder.WebApplicationBuilder.Build()
at Program.<Main>$(String[] args) in source\repos\IntimidatorServer\IntimidatorServer\Program.cs:line 48
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: BL.Interfaces.IDoorsBL Lifetime: Scoped ImplementationType: BL.Services.DoorsBL': Unable resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate 'DAL.Repositories.GenericRepository`1[DAL.Models.Door]'.
Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate 'DAL.Repositories.GenericRepository DAL.Models.Door
GeneriRepository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly DbContext _context;
public GenericRepository(DbContext context)
{
_context = context;
}
public async Task<T> CreateAsync(T obj)
{
await _context.Set<T>().AddAsync(obj);
return obj;
}
public async Task<bool> DeleteAsync(params object[] keys)
{
var entityToDelete = await _context.Set<T>().FindAsync(keys);
if (entityToDelete != null)
{
_context.Set<T>().Remove(entityToDelete);
return true;
}
else
{
return false;
}
}
public async Task<IEnumerable<T>> GetAllAsync(Expression<Func<T, bool>> filter = null)
{
return filter == null ? await _context.Set<T>().ToListAsync() :
(IEnumerable<T>)await _context.Set<T>().Where(filter).ToListAsync();
}
public async Task<T> GetAsync(params object[] keys)
{
return await _context.Set<T>().FindAsync(keys);
}
public async Task SaveChangesAsync()
{
await _context.SaveChangesAsync();
}
public Task<bool> UpdateAsync(T obj)
{
try
{
_context.Set<T>().Attach(obj);
_context.Entry(obj).State = EntityState.Modified;
return Task.FromResult(true);
}
catch (Exception ex)
{
return Task.FromResult(false);
}
}
}
DoorsBL:
public class DoorsBL : IDoorsBL
{
private IGenericRepository<Door> _repository;
public DoorsBL(IGenericRepository<Door> repository)
{
_repository = repository;
}
public async Task<IEnumerable<Door>> GetAvailableDoors()
{
return await _repository.GetAllAsync(d => d.IsAvailble == true);
}
}
program.cs:
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("connectionString")));
builder.Services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
builder.Services.AddScoped<IDoorsBL, DoorsBL>();
dbcontext:
public class AppDbContext : DbContext
{
protected readonly IConfiguration Configuration;
public AppDbContext(IConfiguration configuration)
{
Configuration = configuration;
}
public DbSet<Door> Doors { get; set; }
public DbSet<Intimidator> Intimidators { get; set; }
}
I have no idea what is cuasing it.
>Solution :
builder.Services.AddDbContext<AppDbContext> registers AppDbContext not DbContext, change the repository accordingly:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly AppDbContext _context;
public GenericRepository(AppDbContext context)
{
_context = context;
}
// ...
}
P.S.
Generic repos on top of EF Core context can be considered anti-pattern.