4

I have a Job class with many JobBudgetItems. I am implementing a PATCH method on the controller using Microsoft's built-in JsonPatch library. The issue I'm having is when I try to update a field in a JobBudgetItem, EF Core doesn't persist the change. Instead it creates duplicates of each existing JobBudgetItem with a different Id.

Job

public int Id { get; set; }
public string Name { get; set; }

public IEnumerable<JobBudgetItem> JobBudgetItems { get; set; }

JobBudgetItem

public int Id { get; set; }
public string Category { get; set; }

public int JobId { get; set; }
public Job job { get; set; } 

GET /Job/1

  {
        "id": 1,
        "name": "Test", 
        "jobBudgetItems": [
            {
                "id": 1,
                "category": "ATestCategory",
            },
            {
                "id": 12,
                "category": "BTestCategory",
            }
       ]
 }

PATCH /Job/1

[{
    "op": "replace", "path": "/jobBudgetItems/0/category", "value": "CTestCategory"
}]

JobsController

[HttpPatch("{id}")]
public async Task<IActionResult> PartiallyUpdateJob(int id, [FromBody] JsonPatchDocument<JobDTO> patchJob) 
{

    var jobFromRepo = await _jobManager.GetJobAsync(id);
    var jobUpdateDto = _mapper.Map<JobDTO>(jobFromRepo);
    patchJob.ApplyTo(jobUpdateDto);

    _mapper.Map(jobUpdateDto, jobFromRepo);
    await _jobManager.UpdateJobAsync(jobFromRepo);

    return Ok(_mapper.Map<JobDTO>(jobUpdateDto));

}

Repo

    public async Task<IDataOperationResult> UpdateJobAsync(Job job) {
        _context.Jobs.Update(job);
        try {
            await _context.SaveChangesAsync();
            return new OperationResult(true);
        } catch {
            return new OperationResult(false);
        }
    }

How can I make an update to a JobBudgetItem persist in the database?

4
  • it looks like you need to share your UpdateJobAsync method, not CreateJobAsync Commented Apr 25, 2018 at 15:00
  • @set Oops, I'll get that updated. Thanks. Commented Apr 25, 2018 at 15:07
  • 1
    In your JobsController, after the second map from jobUpdateDto back to jobFromRepo, does your jobFromRepo still have it's id? Could it be that it was nulled by the map and therefore ef creates a new object? Commented Apr 25, 2018 at 19:17
  • @Riscie thanks for sparking that thought. That was my problem. Commented Apr 25, 2018 at 20:12

1 Answer 1

3

It turns out that my implementation of AutoMapper is what threw things off. I opted to ignore the ID on my JobBudgetItemDto (the child record) which was in turn causing the original ID to vanish when it was mapped back before saving to the database.

        CreateMap<JobBudgetItem, JobBudgetItemDTO>()
            .ReverseMap();
            //.ForMember(x => x.Id, opt => opt.Ignore()) // Removed this line.
Sign up to request clarification or add additional context in comments.

Comments

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.