Updating entity with many to many relationship

443 views Asked by At

I have a model with a many to many relationship:

public class Transport
{
    ...
    public virtual ICollection<Remark> CargoRemarks { get; set; }
    ...
}

public class Remark
{
    public virtual ICollection<Transport> Transports { get; set; }
}

In some situations I have to update my Transport model containing some remarks. When adding or removing Remarks the models are not attached (this can't be done due to some architectural decisions).

However without having changed any Remarks in my Transport, the update of my transport object fails:

'...Transport' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

Example:

  • My transport model is created and inserted into the database with some remarks. Everything is working fine and correctly.
  • At a later time this inserted model is loaded again and detached.
  • Without having changed (not added nor removed any remark in the model) my model I want to update it. This leads to this error message.

This is the method I'm calling for updating an entity:

public virtual void Update(TEntity entityToUpdate)
{
    dbSet.Attach(entityToUpdate);
    context.Entry(entityToUpdate).State = EntityState.Modified;
}
2

There are 2 answers

1
Michal Ogluszka On

From my perspective your issue is not related to the M2M relationship. It's common with Attach.

One thing that I would recommend is to consider reloading the entity from db instead of Attach. The reason behind is that you can't be sure that this entity exists in the database in the form that you are trying to attach it.

If this is not an option have you tried not Attaching the entity? If it already has the Entity Key set, it should update itself properly according to:

https://msdn.microsoft.com/en-us/data/jj592676.aspx

3
Shrembo On

In similar problem, I have a generic repo I faced a several problems (attach, M2M relations, ...) this workaround solved them all.

interface IStore<TEntity>
{    
    Task UpdateAsync(int entityid, Func<TEntity?, ValueTask> update);
}

class Store<TEntity> : IStore<TEntity>
{    
    public async Task UpdateAsync(int entityid, Func<TEntity?, ValueTask> update)
    {
        var entity = await dbContext.Set<TEntity>().AsQueryable().Where(x => x.id = entityId).FirstOrDefaultAsync();
        update(entity);
        await dbContext.SaveChangesAsync();
    }
}


public class EntityService
    {
        // ...
        public async Task Update(int id, UpdateParameters parameters)
        {
            await storeInstetance.UpdateAsync(id,
            async entity =>
            {
                if (entity == null)
                {
                    //Do some logic ...
                }
                // update entity values ...
            });
        }
        // ...
    }