Chrillewoodz
Chrillewoodz

Reputation: 28318

Unable to update Entity Framework entry

I got this PATCH endpoint in my C# ASP.NET Core Web API that uses Entity Framework to store my games:

[HttpPatch]
public async Task<ActionResult<Game>> GetGame(long id) {

  var game = await _context.Games.FindAsync(id);

  if (game == null) {
    return NotFound();
  }

  game.State.Map = MapUtils.generateMap();

  _context.Entry(game).State = EntityState.Modified;

  try {
    await _context.SaveChangesAsync();
  }
  catch (DbUpdateConcurrencyException) {
    if (!GameUtils.GameExists(_context, id)) {
      return NotFound();
    }
    else {
      throw;
    }
  }

  return game;
}

When this function is called I get the updated game with Map being set to a List of rows and columns as the response. But then when I use my GET endpoint to retrieve the updated game at a later stage, map is null which means that my entry couldn't have been updated when calling the PATCH.

Here is the GET for retrieving a single game:

[HttpGet("{id}")]
public async Task<ActionResult<Game>> GetGame(long id) {
  var game = await _context.Games.FindAsync(id);

  if (game == null) {
    return NotFound();
  }

  return game;
}

I've tried some solutions from this question but I get the same result.

What am I doing wrong?

Upvotes: 0

Views: 97

Answers (1)

atiyar
atiyar

Reputation: 8326

_context.Entry(game).State = EntityState.Modified;

will mark only the game entity as modified, not it's related entities.

Use -

_context.Games.Update(game);

instead to include the related entities.

Also, take a look at this documentation to understand what this method tries to do behind the scene. Specifically, this part -

"For entity types with generated keys if an entity has its primary key value set then it will be tracked in the Modified state. If the primary key value is not set then it will be tracked in the Added state."

In short, if the related entities don't have primary keys set, EF will try to Add the instead of Updating.

Finally, both in your GET and PATCH method include Map in the query -

var game = await _context.Games.Include(p => p.State).ThenInclude(p => p.Map).FirstOrDefaultAsync(p => p.Id == id);

Take a look at Loading Related Data

Upvotes: 2

Related Questions