C# .NET Core 方法执行多次 - 创建多个线程

问题描述 投票:0回答:1

上下文

通过 Javascript,我对控制器进行 ajax 调用以更新实体“Owner”。控制器使用服务来处理请求,并相应地更新实体。在服务更新方法中我还更新了“Owner”的相关数据,并且在某些情况下我还添加了一个新的实体“Owner”。

问题

这里(在服务中),由于某种原因,

update
方法被多次调用。查看
ThreadPool
列表,它显示多个工作线程处于活动状态。由于这个问题,我最终添加了多个重复的行并更新了不一致的数据(缺少某些字段 - 例如裤子和夹克)。我希望它只运行一次。

如果我只执行

EDIT
操作,不会发生任何不好的事情。

如果我执行 ADD 操作,然后执行 EDIT 操作,则编辑将运行 2 次,在数据库中再添加 2 行。

如果我执行 2 次或更多(让我们称这个数字为 N)ADD 操作,然后执行编辑操作,则编辑将运行 N x 2 次,创建 N x 2 重复行。

我尽可能地减少了代码。它有点长,但我不想排除任何可能实际上是罪魁祸首的情况。

如果提供的最小化代码还不够,我还可以为我们之间的代码向导提供对存储库的访问。请帮我。我真的不知道还有什么可以尝试让它发挥作用。

使用的堆栈:.NET Core 2.2、最新的 jQuery、MySQL、pomelo、EF Core

我已经尝试过的东西:

  • 异步/等待
  • 在 Startup 中将服务和存储库注册为
    Scoped
  • 在 Startup 中将服务和存储库注册为
    Transient
  • 在启动时将 dbContext 注册为
    Transient
  • threadPool.MaxLimit(1,1)
  • js onClick / on ('点击') / one ('点击')
  • 以上所有内容的结合

前端:

<script>
     $(document).one("click", "#buttonId", function () {
     $(this).attr("disabled", "disabled");
     var result = validator.validate(validator);
     if (result.formIsValid) {
     $.ajax({
        type: "POST",
        url: "/controllerName/Edit",
        data: $('#editForm').serialize(),
        dataType: "json",
        success: function (response) {
            CloseModalById('editModal');
            ShowHeaderAlert(response, "success", 5000);
            $('#ownerListState').change();
        },
        error: function (error) {
            CloseModalById('editModal');
            swalErrorTimer(error.responseText, 7000);
        }
        });
       } else {
       updateUi(result.validationResults, "form-group", "error_span");
      }
      });
</script>

控制器:

public OwnerController(IOwnerService ownerService,IMapper mapper)
{
    _ownerService = ownerService;
    _mapper = mapper;
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditModal(OwnerViewModel ownerVM)
{
    try
    {
        var dto = _mapper.Map<OwnerDto> ownerVM);
        var result = _ownerService.UpdateOwner(dto);

        if (result.Successful)
        {
            return Ok(JsonConvert.SerializeObject("Successfully updated!"));
        }

        return BadRequest("Something went wrong!");
    }
    catch (Exception e)
    {
        Log.Error(e, "Something went wrong!");
        return BadRequest("Something went wrong!");
    }
}

服务:

public OwnerService(IOwnerRepository ownerRepository, ICatRepository catRepository, ICatService catService, IMapper mapper)
{
    _ownerRepository = ownerRepository;
    _catRepository = catRepository;
    _catService = catService;
    _mapper = mapper;
}

public Result<OwnerDto> UpdateOwner(OwnerDto ownerDto)
{
    try
    {
        var oldOwner = ownerDto.Copy();

        // case: changed status in other than AtWork =>  empty the position for this set
        if (ownerDto.LocationId != null && ownerDto.Status != "AtWork")
        {
            _catService.UpdateCatPosition(ownerDto.LocationId.Value, ownerDto.Biscuits, PositionEnum.InTheHouse);
        }

        // case: was AtWork, will be in raft => position changed
        if (ownerDto.LocationId != null && ownerDto.Status == "AtWork" 
            && ownerDto.LocationId != null 
            && ownerDto.Biscuits == ownerDto.OldNrOfBiscuits)
        {
            _catService.UpdateCatPosition(ownerDto.LocationId.Value, ownerDto.Biscuits, PositionEnum.InTheHouse);
            _catService.UpdateCatPosition(ownerDto.LocationId.Value, ownerDto.Biscuits, PositionEnum.InTheGarden);
        }

        // case: no change for position but change for nr of biscuits => 
        if (ownerDto.LocationId != null && ownerDto.Status == "AtWork" 
            && ownerDto.Biscuits != ownerDto.OldNrOfBiscuits 
            && ownerDto.LocationId == null)
        {
            ownerDto.LocationId = ownerDto.LocationId;
            // case we have added some new anv to this set => we have to also update the nr inside position
            if (ownerDto.Biscuits > ownerDto.OldNrOfBiscuits)
            {
                var newNrBiscuits = ownerDto.Biscuits - ownerDto.OldNrOfBiscuits;
                var catPosition = PositionEnum.InTheGarden;
                _catService.UpdateCatPosition(ownerDto.LocationId.Value, newNrBiscuits, catPosition);
            }

            // case we have removed some biscuits from this owner => we have to also update the nr for the cat
            if (ownerDto.Biscuits < ownerDto.OldNrOfBiscuits)
            {
                var newNrBiscuits = ownerDto.OldNrOfBiscuits - ownerDto.Biscuits;
                var catPosition = PositionEnum.InTheHouse;
                _catService.UpdateCatPosition(ownerDto.LocationId.Value, newNrBiscuits, catPosition);
            }
        }

        // case: was AtWork, will be AtWork, Position changed, Biscuits changed
        if (ownerDto.LocationId != null && ownerDto.Status == "AtWork" 
            && ownerDto.LocationId != null 
            && ownerDto.LocationId != ownerDto.LocationId 
            && ownerDto.Biscuits != ownerDto.OldNrOfBiscuits)
        {
            var newNrBiscuits = ownerDto.OldNrOfBiscuits -(ownerDto.OldNrOfBiscuits - ownerDto.Biscuits);
            var catPosition = PositionEnum.InTheGarden;
            _catService.UpdateCatPosition(ownerDto.LocationId.Value, newNrBiscuits, catPosition);
        }

        // case: was not AtWork but will be AtWork
        if (ownerDto.LocationId != null && ownerDto.LocationId == null)
        {
            _catService.UpdateCatPosition(ownerDto.LocationId.Value, ownerDto.Biscuits, PositionEnum.InTheGarden);
        }

        if (ownerDto.LocationId != null)
        {
            var catPosition = catRepository.GetPositionById(ownerDto.LocationId.Value);

            if (!catPosition.Successful)
            {
                Log.Error("Something went wrong!");
                throw new Exception("Something went wrong!");
            }

            ownerDto.CatPosition = _mapper.Map<CatDto>(catPosition);
        }

        //------------ Pants
        var pants = _ownerRepository.GetPants(ownerDto.Pants);

        if (!pants.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");
        }

        if (Pants == null && !string.IsNullOrEmpty(ownerDto.Pants))
        {
            pants = _ownerRepository.AddPants(new DbModelPants() { Label = ownerDto.Pants.ToUpper() });
        }

        if (!pants.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");   
        }

        ownerDto.pantsId = pants.Id;

        // Jacket
        var jacket = _ownerRepository.GetjacketByLabel(ownerDto.jacket);

        if (!jacket.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");     
        }

        if (jacket == null && !string.IsNullOrEmpty(ownerDto.Jacket))
        {
            jacket = _ownerRepository.Addjacket(new DbModelJacket() { Label = ownerDto.jacket.ToUpper() });
        }

        if (!jacket.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");         
        }

        ownerDto.JacketId = jacket.Id;

        // ------------------------------------
        var modelForDatabase = _mapper.Map<OwnerDbModel>(ownerDto);
                    
        modelForDatabase.LastModified = DateTime.Now;

        var value = _ownerRepository.UpdateOwner(modelForDatabase);

        if (!value.Successful)
        {
            return Result<OwnerDto>.ResultError(value.Error);
        }

        var returnModel = _mapper.Map<OwnerDto>(value);

        // if we move the biscuits we need to create a new owner with the remaining biscuits values that were not moved to the new location
        //--------- This adds a new Owner to the db with oldData
        if (oldOwner.OldNrOfBiscuits > oldOwner.Biscuits 
            && oldOwner.LocationId != oldOwner.LocationId 
            && oldOwner.LocationId != null && oldOwner.LocationId != null)
        {
            oldOwner.Biscuits = oldOwner.OldNrOfBiscuits - oldOwner.Biscuits;
            oldOwner.LocationId = oldOwner.LocationId;
                       
            oldOwner.Id = 0;

            var addedOldSet = AddOwner(oldOwner, PositionEnum.AtThePetStore);

            if (!addedOldSet.Successful)
            {
                Log.Error("log stuff here");
                throw new Exception("Something went wrong!");       
            }
        }

        return Result<OwnerDto>.ResultOk(returnModel);
    }
    catch (Exception er)
    {
        Log.Error("log stuff here");
        throw new Exception("Something went wrong!");      
    }
}

public Result<OwnerDto> AddOwner(OwnerDto owner, PositionEnum catPosition = PositionEnum.InTheGarden)
{
    try
    {
        if (owner.LocationId != null && owner.Status == "AtWork")
        {
            var catPosition = _catService.GetPositionById(owner.LocationId.Value);

            if (!catPosition.Successful)
            {
                Log.Error("log stuff here");
                throw new Exception("Something went wrong!");          
            }

            _catService.UpdatePosition(owner.LocationId.Value, owner.NrBucati, catPosition);
               
            catPosition = _catService.GetPositionById(owner.LocationId.Value);
            owner.CatPosition = catPosition;
        }

        //------------ Pants
        // if we don't find the pants with provided name in the table Pants, we add a new set of Pants and provide the Owner with that set. Same for the Jacket.
        var pants = _ownerRepository.GetPants(ownerDto.Pants);

        if (!pants.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");
        }

        if (Pants == null && !string.IsNullOrEmpty(ownerDto.Pants))
        {
            pants = _ownerRepository.AddPants(new DbModelPants() { Label = ownerDto.Pants.ToUpper() });
        }

        if (!pants.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");   
        }

        ownerDto.PantsId = pants.Id;

        //----------- Jacket
        var jacket = _ownerRepository.GetjacketByLabel(ownerDto.Jacket);

        if (!jacket.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");     
        }

        if (jacket == null && !string.IsNullOrEmpty(ownerDto.Jacket))
        {
            jacket = _ownerRepository.Addjacket(new DbModelJacket() { Label = ownerDto.jacket.ToUpper() });
        }

        if (!jacket.Successful)
        {
            Log.Error("log stuff here");
            throw new Exception("Something went wrong!");         
        }

        ownerDto.JacketId = jacket.Id;

        var modelForDatabase = _mapper.Map<OwnerDbModel>(owner);
        modelForDatabase.LastModified = DateTime.Now;
        modelForDatabase.Name = modelForDatabase.Name.ToUpper();

        // send model to database
        var addedOwner = _ownerRepository.AddOwnerToDatabase(modelForDatabase);
        var returnModel = _mapper.Map<OwnerDto>(addedOwner);

        return Result<OwnerDto>.ResultOk(returnModel);
    }
    catch (Exception er)
    {
        Log.Error("log stuff here");
        throw new Exception("Something went wrong!");         
    }
}

所有存储库内的更新和添加方法都是类似的。

示例:

    public Entity UpdateEntity(Entity entityToUpdate)
    {
          _db.EntityDbSet.Update(entityToUpdate);
          _db.SaveChanges();
          return entityToUpdate;
    }
    
    public Entity AddEntity(Entity entityToAdd)
    {
          _db.EntityDbSet.Add(entityToAdd);
          _db.SaveChanges();
          return entityToAdd;
    }
ajax asp.net-core thread-safety dbcontext lifetime
1个回答
1
投票

问题出在 HTML 文件中。包含模式的部分视图也加载了 js 文件,因此它加载了多次。这就是多个电话的来源。为了使其工作,我在 Index.js 中加载了 js 文件。对于一个疯狂问题的简单解决方案却带来了疯狂的结果......

© www.soinside.com 2019 - 2024. All rights reserved.