Is this an EF Core bug or an I doing it wrong to update one entity?

.net-core asp.net-core c# entity-framework entity-framework-core

Question

I'm using Entity Framework Core together with the repository pattern. To help me out, I coded one base repository with the basic CRUD methods. The update method is as follows:

public void Update(TEntity entity)
{
    var contextEntry = _context.Entry<TEntity>(entity);
    if (contextEntry.State == EntityState.Dettached)
    {
        _context.Attach(entity);
    }
    contextEntry.State = EntityState.Modified;
    _context.SaveChanges();
}

Given the BaseRepository class containing this method, I created one User repository inheriting from this

public class UserRepository : BaseRepository<User>, IUserRepository
{
}

And I've used this in the PUT method of one Web API coded with ASP.NET Core

[HttpPut("~/api/users/{id}")]
public IActionResult Put(int id, [FromBody] User user)
{
    if (user == null || user.UserId != id)
    {
        return BadRequest();
    }

    userRepository.Update(user);
    return new NoContentResult();
}

Now, when issuing a request, I get one error in the _context.Attach(entity) line. The exception says that it can't add the entity for tracking because there is already another entity with the same key being tracked.

When debugging I saw that contextEntry.State was set to Unchanged. Hence, it is obviously not equal to EntityState.Dettached. Still, the execution got inside the if statement and tried to attach the entity.

Something is quite wrong here. Is this a bug? Or am I doing something very wrong? I believe that I'm the one doing something very wrong with this update strategy, but I'm unsure about it. In that case, what is wrong with my approach?

EDIT: I updated the Update method to use just _context.Update(entity) and after _context.SaveChanges(). Still, the _context.Update(entity) throws one InvalidOperationException with this message:

Additional information: The instance of entity type 'User' cannot be tracked because another instance of this type with the same key is already being tracked. When adding new entities, for most key types a unique temporary key value will be created if no key is set (i.e. if the key property is assigned the default value for its type). If you are explicitly setting key values for new entities, ensure they do not collide with existing entities or temporary values generated for other new entities. When attaching existing entities, ensure that only one entity instance with a given key value is attached to the context.

1
1
12/26/2016 2:48:06 PM

Popular Answer

All the information is in the exception message... you already have another copy of the entity with that primary key attached.

I would recommend one of the following (preferred first):

  1. Use a new Context for each action, don't have a long-lived repository/context
  2. Use .Set<TEntity>.Find(object[] key) on your context using the Primary Key, in order to retrieve any entity you already have.
  3. In your current update method, use the Set<TEntity>.Local.Find(..) to check if it already exists
0
12/27/2016 2:37:43 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow