You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

注入泛型仓储至BL服务时遇DbContext解析异常求助

问题描述

原本将GenericRepository注入BL服务用于从Entity Framework获取数据时无异常,但添加另一个Scoped生命周期的BL服务后,抛出以下异常:

System.AggregateException HResult=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 to 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

相关代码

GenericRepository代码

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; }
}
解决方案

问题根源在于:GenericRepository<T>的构造函数依赖抽象类DbContext,但DI容器中仅注册了具体的AppDbContext类型,未将DbContext抽象映射到AppDbContext实现,导致容器无法找到DbContext的实例完成注入。

有两种解决方式:

方式一:修改GenericRepository依赖具体的AppDbContext

将GenericRepository<T>的构造函数参数改为AppDbContext:

private readonly AppDbContext _context;

public GenericRepository(AppDbContext context)
{
    _context = context;
}

这种方式更直接,因为项目中实际使用的就是AppDbContext,无需依赖抽象的DbContext。

方式二:在DI容器中注册DbContext到AppDbContext的映射

在Program.cs中添加一行注册,让容器知道当需要DbContext时,提供AppDbContext的实例:

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("connectionString")));
// 添加这行映射
builder.Services.AddScoped<DbContext>(sp => sp.GetRequiredService<AppDbContext>());
builder.Services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
builder.Services.AddScoped<IDoorsBL, DoorsBL>();

两种方式任选其一即可解决依赖注入的解析问题。

内容的提问来源于stack exchange,提问作者Tal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:55:57