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

.NET Core 6 MVC依赖注入报错:激活控制器时无法解析RepositoryPersonal服务

问题描述

我创建了一个采用依赖注入(Dependency Injection)和仓储模式(Repository Pattern)的.NET Core 6 MVC应用,尝试将RepositoryPersonal注入到PersonalController中时出现错误。

错误信息:

InvalidOperationException: Unable to resolve service for type 'AqcCalama.Repositories.RepositoryPersonal' while attempting to activate 'AqcCalama.Controllers.PersonalController'.

相关代码

仓储类(Repository):

public class RepositoryPersonal
{
    private ApplicationDbContext context;

    public RepositoryPersonal(ApplicationDbContext context)
    {
        this.context = context;
    }

    public List<Personal> GetPersonal()
    {
        return this.context.Personal.ToList();
    }

    public List<Personal> GetPersonal(string rut)
    {
        var consulta = from datos in this.context.Personal
                       where datos.Rut.Contains(rut)
                       select datos;
        return consulta.ToList();
    }
}

控制器(Controller):

public class PersonalController : Controller
{
    private RepositoryPersonal repo;

    public PersonalController(RepositoryPersonal repo)
    {
        this.repo = repo;
    }

    public IActionResult Index()
    {
        return View();
    }

    public IActionResult BuscadorPersonal()
    {
        return View();
    }

    [HttpPost]
    public IActionResult BuscadorPersonal(string rut)
    {
        List<Personal> per = this.repo.GetPersonal(rut);

        return View(per);
    }
}

Program.cs:

builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddDefaultIdentity<IdentityUser>().AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddControllersWithViews();

请问这个问题可能是什么原因?


解决方案

核心原因

.NET Core的依赖注入(DI)容器只会自动管理已注册的服务类型。你没有将RepositoryPersonal注册到DI容器中,所以容器无法创建该类的实例,也就无法注入到PersonalController中。

快速修复

在Program.cs的服务配置区域,添加一行代码注册RepositoryPersonal:

// 注册仓储服务,使用Scoped生命周期(与DbContext默认生命周期一致,推荐)
builder.Services.AddScoped<RepositoryPersonal>();

修改后的完整Program.cs服务配置代码:

builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddDefaultIdentity<IdentityUser>().AddEntityFrameworkStores<ApplicationDbContext>();

// 新增:注册RepositoryPersonal到DI容器
builder.Services.AddScoped<RepositoryPersonal>();

builder.Services.AddControllersWithViews();

生命周期说明

  • AddScoped:每个HTTP请求创建一个服务实例,和ApplicationDbContext的默认生命周期匹配,能避免上下文实例冲突,是仓储类的最优选择。
  • 如果有特殊需求,也可以使用AddSingleton(全局单例)或AddTransient(每次请求创建新实例),但不推荐用于依赖DbContext的仓储类。

仓储模式最佳实践(可选)

为了更好地解耦和支持单元测试,建议给仓储定义接口,再注册接口与实现类:

  1. 定义仓储接口
public interface IRepositoryPersonal
{
    List<Personal> GetPersonal();
    List<Personal> GetPersonal(string rut);
}
  1. 修改仓储类实现接口
public class RepositoryPersonal : IRepositoryPersonal
{
    private ApplicationDbContext context;

    public RepositoryPersonal(ApplicationDbContext context)
    {
        this.context = context;
    }

    // 原有方法实现不变
    public List<Personal> GetPersonal()
    {
        return this.context.Personal.ToList();
    }

    public List<Personal> GetPersonal(string rut)
    {
        var consulta = from datos in this.context.Personal
                       where datos.Rut.Contains(rut)
                       select datos;
        return consulta.ToList();
    }
}
  1. 注册接口与实现类
builder.Services.AddScoped<IRepositoryPersonal, RepositoryPersonal>();
  1. 修改控制器依赖接口
public class PersonalController : Controller
{
    private readonly IRepositoryPersonal _repo;

    public PersonalController(IRepositoryPersonal repo)
    {
        _repo = repo;
    }

    // 原有方法逻辑不变
}

这种方式的优势在于:后续如果需要替换仓储实现(比如用模拟类做单元测试),无需修改控制器代码,只需要更换DI注册的实现类即可。


内容的提问来源于stack exchange,提问作者José Eduardo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 14:05:36