1

Below is the code of my API, but it always returns a 500 Internal server error. The exception is thrown when executing SaveChangesAsync().

The instance of entity type 'NewsReport' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values

[HttpPut("{id}")]
public async Task<IActionResult> EditDevblog([FromBody] DevblogModel devblog, int id)
{
    if (!ModelState.IsValid)
        return BadRequest();

    var devblogInDb = _context.DevblogModels
        .Include(d => d.Fixs)
        .Include(d => d.News)
        .Include(d => d.Removes)
        .Include(d => d.Updates)
        .SingleOrDefault(d => d.Id == id);

    if (devblogInDb == null)
        return NotFound();

    devblogInDb.Fixs = devblog.Fixs;
    devblogInDb.News = devblog.News;
    devblogInDb.Removes = devblog.Removes;
    devblogInDb.Updates = devblog.Updates;
    devblogInDb.PatchName = devblog.PatchName;

    await _context.SaveChangesAsync();
    var h = _context.DevblogModels.SingleOrDefault(d => d.Id == id);
    return Ok();
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
Pavel B.
  • 843
  • 1
  • 7
  • 17
  • 3
    I agree too. If you can't easily step into the exception in debug mode, you could return 500 and pass the exception message back to the client. Note you probably don't want to pass that message back in production though as it may contain info the client shouldn't know about. – TTT May 23 '18 at 18:13
  • 1
    `_context` is instance of class DbContext. @Brian i think thats clear becose of the saveChangesAsync() method and based on what i want to do. – Pavel B. May 23 '18 at 18:15
  • 1
    @PavelB. at least now those trying to help you have something to work with. that error should be added to the question. I have already done it for you, but remember that for future questions. – Nkosi May 23 '18 at 18:29
  • 2
    It's very odd to have a DbContext that is instantiated outside of the "scope" of the WebAPI method that is using it. If `_context` is static then you will definitely run into issues as your project grows. – Sam Axe May 23 '18 at 18:34
  • 1
    @SamAxe no its not static. `_context` injected by service and disposed when the controler is disposing. – Pavel B. May 23 '18 at 18:37
  • 2
    Please see my answer [here](https://stackoverflow.com/a/50488234/6794089). EF Core isn't capable of detecting/cascading updates/adds when setting a child entity property directly. – bman7716 May 23 '18 at 18:43
  • 2
    Possible duplicate of [Entity Framework Core: Fail to update Entity with nested value objects](https://stackoverflow.com/questions/50486669/entity-framework-core-fail-to-update-entity-with-nested-value-objects) – bman7716 May 23 '18 at 18:44

1 Answers1

0

Please see my answer here.

EF Core throws this exception when you replace a child entity instance with a new one like you are doing here:

devblogInDb.Fixs = devblog.Fixs;
devblogInDb.News = devblog.News;
devblogInDb.Removes = devblog.Removes;
devblogInDb.Updates = devblog.Updates;
devblogInDb.PatchName = devblog.PatchName;

Unfortunately the only workable alternative has been to update the current child entity properties directly. Per my original answer:

// In your DevblogModels and assuming a 1:1 relationship
public void SetNewsReport(NewsReport newsReport)
{   
    this.News.UpdateFrom(newsReport);
}

// Then, on your NewsReport entity
internal void UpdateFrom(NewsReport other)
{
    this.Title = other.Title;
    this.Article = other.Article;
    // other properties...
}

The second approach in my original answer suggests to detach the entity, replace the child instance, then reattach and try to save. In my attempts with this approach the exception went away, but the data did not persist to the database. Maybe you'll have better luck with it than I did...

context.Entry(devblogInDb).State = EntityState.Detached;
devblogInDb.Fixs = devblog.Fixs;
devblogInDb.News = devblog.News;
devblogInDb.Removes = devblog.Removes;
devblogInDb.Updates = devblog.Updates;
devblogInDb.PatchName = devblog.PatchName;
context.Entry(devblogInDb).State = EntityState.Modified;

A Bit Further

As my original answer suggests this has been a longstanding issue with EF Core. This issue was supposed to be fixed in EF Core 2.1, however, the OP of my original answer was using the release candidate for EF Core 2.1. Apparently this issue either didn't make the cut or the fixes put in place still have a few bugs in them (it is just a release candidate after all...)

For a great read on this topic Julie Lerman posted an article in the MSDN magazine that you can find here. She also has a few alternative solutions that you could use as well.

bman7716
  • 693
  • 7
  • 14