EF core 5 Update entity with Many to many ( the instance of entity type cannot be tracked)

I have many to many relation between Ad and Category classes.

I have Ad details page where I want to update that Ad.

In UI categories is implemented as Select2 with multiple values.

When I update ad I get error that instance of category is already being tracked.(the instance of entity type cannot be tracked because another instance with the same key value for {'Id'} is already being tracked )

Here is my code of retrieving ad to show on details page, and also code for updating ad.

public async Task<Ad> GetById(int id)
        {
            return await _databaseContext.Ads.Include(x => x.SchoolLevels).Include(x => x.Categories).Include(x => x.Images).FirstOrDefaultAsync(x => x.Id == id);
        }


        public async Task<Ad> Update(Ad ad)
        {
            _databaseContext.Entry(ad).State = EntityState.Modified;

            _ = await _databaseContext.SaveChangesAsync();
            return ad;
        }

It seems very common scenario. I have detail page and in some select box I have to choose multiple values.

Here is my UI code (Blazor)

                    <div class="form-group">
                        <label>Categories</label>
                       
                        <Select2 TItem="Categories"
                                 TSource="List<Category>"
                                 IdSelector="@(i => i != null ? i.Id.ToString() : "")"
                                 TextSelector="i => i.Name"
                                 Datasource="Categories"
                                 Multiselect="true"
                                 Value="@Ad.Categories"
                                 GetElementById="(items, filter, token) => Task.FromResult(items.SingleOrDefault(i => i.Id.ToString().Equals(filter)))"
                                 FilterFunction="(items, filter, token) => Task.FromResult(items.Where(i => i.Name.ToLower().StartsWith(filter.ToLower())).ToList())">

                        </Select2>
                    </div>
 
                    </div>
                    <SaveButton IsSaving="IsSaving" />
 
                </EditForm> 

1 answer

  • answered 2021-01-18 19:11 Sergey

    Try to change your update action code to this. You have an error that instance is already being tracked. This code will find this tracked instance and update it:

    public async Task<Ad> Update(Ad ad)
    {
            var existItem = await  _databaseContext.Set<Ad>().FindAsync(ad);
          //or you can try
            var existItem = await  _databaseContext.Set<Ad>()
                        .Where(i=>i.Id == ad.Id)  
                         .FirstOrDefaultAsync();
    
    
            if (existItem != null)
            {
            _databaseContext.Entry(existItem).CurrentValues.SetValues(ad);
            var result = await _databaseContext.SaveChangesAsync();
            if (result == 0)  ... error code;
            } else  ...erorr code
    
           return ad;
     }