.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的仓储类。
仓储模式最佳实践(可选)
为了更好地解耦和支持单元测试,建议给仓储定义接口,再注册接口与实现类:
- 定义仓储接口
public interface IRepositoryPersonal { List<Personal> GetPersonal(); List<Personal> GetPersonal(string rut); }
- 修改仓储类实现接口
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(); } }
- 注册接口与实现类
builder.Services.AddScoped<IRepositoryPersonal, RepositoryPersonal>();
- 修改控制器依赖接口
public class PersonalController : Controller { private readonly IRepositoryPersonal _repo; public PersonalController(IRepositoryPersonal repo) { _repo = repo; } // 原有方法逻辑不变 }
这种方式的优势在于:后续如果需要替换仓储实现(比如用模拟类做单元测试),无需修改控制器代码,只需要更换DI注册的实现类即可。
内容的提问来源于stack exchange,提问作者José Eduardo
相关产品推荐
相关产品推荐

