ASP.NET Core 6启动报错无法解析EFContext导致服务构造失败如何解决
启动应用时抛出如下聚合异常:
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Data.Access.Layer.Interfaces.IUnitOfWork Lifetime: Scoped ImplementationType: Data.Access.Layer.Repositories.UnitOfWork': Unable to resolve service for type 'Data.Access.Layer.EFContext' while attempting to activate 'Data.Access.Layer.Repositories.UnitOfWork'.)'
相关实现代码:
// IUnitOfWork接口定义 public interface IUnitOfWork: IDisposable { IGenericRepository<ApplicationUser> Users { get; } IGenericRepository<Painting> Paintings { get; } IGenericRepository<OrderItem> OrdersItems { get; } IGenericRepository<Order> Orders { get; } IGenericRepository<ShoppingCartItem> ShoppingCartItems { get; } } // UnitOfWork实现 public class UnitOfWork : IUnitOfWork { private readonly EFContext _eFContext; private GenericRepository<ApplicationUser> _users; private GenericRepository<Painting> _paintings; private GenericRepository<Order> _orders; private GenericRepository<OrderItem> _ordersItems; private GenericRepository<ShoppingCartItem> _shoppingCartItems; public UnitOfWork(EFContext eFContext) { _eFContext = eFContext; } public IGenericRepository<ApplicationUser> Users => _users ??= new GenericRepository<ApplicationUser>(_eFContext); public IGenericRepository<Painting> Paintings => _paintings ??= new GenericRepository<Painting>(_eFContext); public IGenericRepository<Order> Orders => _orders??= new GenericRepository<Order>(_eFContext); public IGenericRepository<OrderItem> OrdersItems => _ordersItems ??= new GenericRepository<OrderItem>(_eFContext); public IGenericRepository<ShoppingCartItem> ShoppingCartItems => _shoppingCartItems ??= new GenericRepository<ShoppingCartItem>(_eFContext); private bool disposed = false; public virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { _eFContext.Dispose(); } this.disposed = true; } } void IDisposable.Dispose() { Dispose(true); GC.SuppressFinalize(this); } }
Program.cs配置代码:
using AutoMapper; using Business.Layer.Interfaces; using Business.Layer.Services; using Data.Access.Layer.Entities; using Data.Access.Layer.Interfaces; using Data.Access.Layer.Repositories; using Presentation.Layer.Mapping; var builder = WebApplication.CreateBuilder(args); // 向依赖注入容器添加服务 builder.Services.AddScoped<IUnitOfWork, UnitOfWork>(); builder.Services.AddRazorPages(); builder.Services.AddControllersWithViews(); builder.Services.AddAutoMapper(typeof(AutoMapperProfile).Assembly, typeof(BLAutoMapperProfile).Assembly); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.UseRouting(); app.UseAuthorization(); app.MapRazorPages(); app.Run();
依赖注入容器在实例化UnitOfWork时,需要注入其构造函数依赖的EFContext类型,但你没有将EFContext注册到DI服务容器中,导致容器无法解析该依赖,最终抛出服务构造失败的异常。
- 确认项目已安装对应数据库提供程序的EF Core相关NuGet包,例如使用SQL Server需安装
Microsoft.EntityFrameworkCore.SqlServer。 - 检查
EFContext类的构造函数是否符合DI注入要求,正确写法如下:
public class EFContext : DbContext { public EFContext(DbContextOptions<EFContext> options) : base(options) { } // 定义你的实体DbSet属性 public DbSet<ApplicationUser> ApplicationUsers { get; set; } public DbSet<Painting> Paintings { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<OrderItem> OrderItems { get; set; } public DbSet<ShoppingCartItem> ShoppingCartItems { get; set; } }
- 在Program.cs的服务注册阶段(
builder.Build()调用之前),使用AddDbContext方法注册EFContext,生命周期保持默认的Scoped即可,和UnitOfWork生命周期匹配不会出现冲突。修改后的服务注册部分代码如下:
var builder = WebApplication.CreateBuilder(args); // 向依赖注入容器添加服务 // 注册EFContext数据库上下文,根据你使用的数据库替换对应提供程序方法和连接字符串配置 builder.Services.AddDbContext<EFContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); builder.Services.AddScoped<IUnitOfWork, UnitOfWork>(); builder.Services.AddRazorPages(); builder.Services.AddControllersWithViews(); builder.Services.AddAutoMapper(typeof(AutoMapperProfile).Assembly, typeof(BLAutoMapperProfile).Assembly); var app = builder.Build(); // 其余中间件配置无需修改
注意:如果你使用的不是SQL Server数据库,将UseSqlServer替换为对应数据库的配置方法即可,例如SQLite使用UseSqlite、MySQL使用UseMySql,同时确保appsettings.json中已经配置了正确的数据库连接字符串。
内容的提问来源于stack exchange,提问作者user19300576

