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

迁移至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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:43:37