首页 > 解决方案 > 使用依赖注入的多线程连接对象

问题描述

我一直在尝试在现有应用程序中添加并行 foreach,但遇到了一个奇怪的问题

应用架构

  1. 控制器解析BO层
  2. BO层解析服务层
  3. 服务层解析 UOW 和存储库层
  4. UOW 层解析数据库连接

BO层

private IUserService _userService; 
public BOUser(IUserService userService) => _userService=userService; 

public void AddUser(User user) => _userService.addUser(user);

服务层

private IUnitofWork _uow;
private IUserRepository _userRepo;
UserService(IUOW _uow, IUserRepository _userRepo)
{
    uow = _uow;
    _userRepo.uow = _uow;
}

public void AddUser (User user) {
    _uow.BeginTransaction();
    _userRepo.Add(user);
    _uow.CommitTransaction();
}

回购层

public IUnitOfWork UnitOfWork { get; set; }
public void Add(user){
    UnitOfWork.Connection.Insert<UserContact>(userContact, UnitOfWork.Transaction);
}

工作单元

public UnitOfWork(IDbConnection connection)
{
    Connection = connection; // responsible for creating new connection
}

这在今天工作正常,但是当我尝试在 BO 层中使用 parallel.foreach 添加多个用户时,我得到一个失败和一个成功

背后的原因是服务层在 BO 层启动时启动,当我尝试多个线程时,整个进程的 UOW.connection 仍然为 1,因为 Connection 是一个在多个线程之间共享的对象,它失败了,因为一个线程完成了工作并关闭了 Connection 对象

我通过从构造函数中删除 UOW 并使用服务位置模式来考虑解决方案

IUserSrevice userService = new UserService();

这将基于线程创建多个连接对象。

这不是仪式的方式。任何专家意见都会有所帮助

标签: multithreadingdependency-injectionunit-of-work

解决方案


Connection不是线程安全的对象,因为它的想法是创建一个连接对象池,并让每个线程从池中借用一个连接,完成其工作并在完成后将其返回到池中。

因此,一次最多只能有一个线程访问一个连接对象。

您应该注入连接池而不是单个连接对象。


推荐阅读