迁移至ASP.NET Core:如何结合依赖注入实现UnitOfWork模式?
Hey Vlad, 刚看到你要从ASP.NET MVC迁移到ASP.NET Core,还想沿用UnitOfWork模式,同时保持之前三层架构的解耦方式——我完全懂你想要的那种分层清爽感,下面给你一步步拆解怎么实现:
第一步:对齐ASP.NET Core的依赖注入逻辑
你之前用Ninject做注入,ASP.NET Core自带了原生的依赖注入容器,功能足够且更贴合框架生态,咱们先基于原生DI来实现,要是之后还是想用Ninject也可以兼容,但原生的更省心。
第二步:保持你的三层架构(DAL/BLL/Web),各司其职
咱们还是把代码按DAL(数据访问)、BLL(业务逻辑)、Web(UI)分层,确保Web层不用直接引用DAL的DLL,完全通过BLL做中转:
1. DAL层:实现UnitOfWork和Repository
首先在DAL层定义IUnitOfWork接口和具体实现,同时搭配Repository模式(这也是你之前MVC里常用的组合):
// DAL/Interfaces/IUnitOfWork.cs public interface IUnitOfWork : IDisposable { // 替换成你的实体对应的Repository接口 IProductRepository Products { get; } IOrderRepository Orders { get; } Task<int> SaveChangesAsync(); } // DAL/Implementations/UnitOfWork.cs public class UnitOfWork : IUnitOfWork { private readonly AppDbContext _dbContext; private IProductRepository _productRepo; private IOrderRepository _orderRepo; public UnitOfWork(AppDbContext dbContext) { _dbContext = dbContext; } // 懒加载Repository实例 public IProductRepository Products => _productRepo ??= new ProductRepository(_dbContext); public IOrderRepository Orders => _orderRepo ??= new OrderRepository(_dbContext); public async Task<int> SaveChangesAsync() { return await _dbContext.SaveChangesAsync(); } public void Dispose() { _dbContext.Dispose(); } }
这里的AppDbContext是你的EF Core上下文,记得在DAL层里配置好实体映射。
2. BLL层:依赖IUnitOfWork实现业务逻辑
BLL层只依赖IUnitOfWork接口,不用关心具体实现,完美解耦:
// BLL/Services/IProductService.cs public interface IProductService { Task<Product> GetProductByIdAsync(int id); Task CreateProductAsync(ProductCreateDto dto); } // BLL/Services/ProductService.cs public class ProductService : IProductService { private readonly IUnitOfWork _unitOfWork; // 通过构造函数注入IUnitOfWork public ProductService(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public async Task<Product> GetProductByIdAsync(int id) { return await _unitOfWork.Products.GetByIdAsync(id); } public async Task CreateProductAsync(ProductCreateDto dto) { var product = new Product { Name = dto.Name, Price = dto.Price // 其他属性映射 }; _unitOfWork.Products.Add(product); await _unitOfWork.SaveChangesAsync(); } }
3. Web层:配置DI,不用引用DAL
在ASP.NET Core的Program.cs(.NET 6+)里注册依赖,Web层只需要引用BLL层的DLL就行,完全不用碰DAL:
// Program.cs var builder = WebApplication.CreateBuilder(args); // 1. 注册EF Core上下文(从appsettings.json读连接字符串) builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 2. 注册UnitOfWork和业务服务 builder.Services.AddScoped<IUnitOfWork, UnitOfWork>(); builder.Services.AddScoped<IProductService, ProductService>(); // 其他配置:比如添加控制器、视图等 builder.Services.AddControllersWithViews(); var app = builder.Build(); // 中间件配置(省略) app.Run();
这里的AddScoped是指定生命周期:每个HTTP请求创建一个实例,和DbContext的默认生命周期一致,刚好符合UnitOfWork的需求——一个请求内的所有操作共享同一个上下文。
额外注意点
- 如果你之前习惯用Ninject,也可以安装
Ninject.AspNetCore包,然后在Program.cs里替换原生DI容器,但原生DI已经能满足大部分场景,更推荐用原生的。 - 连接字符串放在
appsettings.json里,不要硬编码,和ASP.NET Core的配置系统对齐:{ "ConnectionStrings": { "DefaultConnection": "Server=.;Database=YourDb;Trusted_Connection=True;TrustServerCertificate=True;" } } - 确保DAL层的
AppDbContext、IUnitOfWork等接口都被BLL层引用,Web层只需要引用BLL的服务接口即可。
这样下来,你的架构和之前ASP.NET MVC里的分层解耦逻辑完全一致,同时适配了ASP.NET Core的生态~
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

