Search code examples
c#asp.nettypescriptapientity-framework

The instance of entity type 'IngredientEntity' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked


I have two db tables, one for recipes and one for ingredients, but when I try to update the database it throws the exception above.

My api controller is

    [HttpPost("saveRecipe")]
    public async Task<ActionResult<SaveRecipeResponse>> SaveRecipe(SaveRecipeRequest request, CancellationToken requestAborted)
    {
            await _recipeRepo.UpsertAsync(_mapper.Map<RecipeEntity>(request.Recipe), requestAborted);
            foreach (var ing in request.Recipe.Ingredients)
            {
                await _ingRepo.UpsertAsync(_mapper.Map<IngredientEntity>(ing), requestAborted);            
            }
await _uow.SaveAsync();
            return new SaveRecipeResponse() { Recipe = request.Recipe, Success = true };
            // </custom:SaveRecipe>
    }

The client send this request:

save() {
    this.delegates.recipes.SaveRecipe(this.payload.recipe).subscribe({
      next: (res) => {
        this.isReady = false;
        console.log(res);
      },
      error: (err) => {
        this.isReady = true;
        this.errorMsg = {message: 'save-error', details: err.message};
        console.log(err);
      },
      complete: () => {
        this.isReady = true;
        this.return();
      }
    })
  }

how can i insert all of the ingredients in the database? every ingredient should have a different ID so i don't know why does it throw this


Solution

  • Thanks to CodeCaster's comment, I found out data should be mapped only once. So I now save the mapped entity in a variable and then use it directly.

    [HttpPost("saveRecipe")]
    // <custom:customAttributesSaveRecipe>
        // </custom:customAttributesSaveRecipe>
    public async Task<ActionResult<SaveRecipeResponse>> SaveRecipe(SaveRecipeRequest request, CancellationToken requestAborted)
    {
            // <custom:SaveRecipe>
            RecipeEntity r = _mapper.Map<RecipeEntity>(request.Recipe);
            await _recipeRepo.UpsertAsync(r, requestAborted);
            foreach (var ing in r.Ingredients)
            {
                await _ingRepo.UpsertAsync(ing, requestAborted);            
            }
    
            await _uow.SaveAsync();
    
            return new SaveRecipeResponse() { Recipe = request.Recipe, Success 
    = true };
            // </custom:SaveRecipe>
    }