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">
                        <Select2 TItem="Categories"
                                 IdSelector="@(i => i != null ? i.Id.ToString() : "")"
                                 TextSelector="i => i.Name"
                                 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())">

                    <SaveButton IsSaving="IsSaving" />

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)  
            if (existItem != null)
            var result = await _databaseContext.SaveChangesAsync();
            if (result == 0)  ... error code;
            } else  ...erorr code
           return ad;