2

I am trying to update a many-to-many relation in a ASP.NET Core MVC controller using Entity Framework Core. I managed to get this working for adding to the relation, but not updating (leads to a duplicate key error, if I just open/save the entity).

How can I remove the relations from the database before updating/inserting new relations in an efficient way?

public async Task<IActionResult> Edit(int id, [Bind("Id,Name,SalesClerkIds")] Plant plant)
{
        if (id != plant.Id)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            try
            {
                plant.SalesClerks = new List<PlantSalesClerk>();

                if (plant.SalesClerkIds != null)
                {
                    foreach (var scId in plant.SalesClerkIds)
                    {
                        plant.SalesClerks.Add(new PlantSalesClerk()
                        {
                            Plant = plant,
                            User = _context.Users.FirstOrDefault(u => u.Id == scId)
                        });
                    }
                }

                _context.Update(plant);

                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!PlantExists(plant.Id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return RedirectToAction(nameof(Index));
        }

        return View(plant);
  }

1 Answer 1

3

Write your Edit post method as follows:

public async Task<IActionResult> Edit(int id, [Bind("Id,Name,SalesClerkIds")] Plant plant)
{
    if (id != plant.Id)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            Plant plantToBeUpdated = await _context.Plants.Include(p => p.SalesClerks).FirstOrDefaultAsync(p => p.Id == id);

            if (plantToBeUpdated != null)
            {
                 plantToBeUpdated.SalesClerks.Clear(); // Here you have to clear the existing children before adding the new

                 if (plant.SalesClerkIds.Count > 0)
                 {
                      foreach (var scId in plant.SalesClerkIds)
                      {
                         plantToBeUpdated.SalesClerks.Add(new PlantSalesClerk()
                         {
                            PlantId = plantToBeUpdated.Id,
                            UserId = scId
                         });
                     }
                 }

                 plantToBeUpdated.Name = plant.Name;

                // Map other properties here if any

                _context.Plants.Update(plantToBeUpdated);

                await _context.SaveChangesAsync();
           }

        }
        catch (DbUpdateConcurrencyException)
        {
            if (!PlantExists(plant.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return RedirectToAction(nameof(Index));
    }

    return View(plant);
}

Note: I didn't see your model classes and edit view. I have assumed everything based on your code. So there may needs to be some adjustment but this is the concept of updating model with children in EF core.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot... its working this way! I thought there would be a more "automated" way of doing this, but Im also fine with this solution.
So, it is just - "Remove everything and add it as new". ..?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.