I'm trying to update an entity Tender, this entity has a List of TenderOffer and this TenderOffer has a Company entity. When I try to update the Tender I'm getting the following error
Message=The instance of entity type 'Company' cannot be tracked because another instance with the key value '{ID: 4}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
Source=Microsoft.EntityFrameworkCore StackTrace: at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntryentry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKeykey, InternalEntityEntry entry, Boolean updateDuplicate) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKeykey, InternalEntityEntry entry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(InternalEntityEntryentry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntryentry) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityStateoldState, EntityState newState, Boolean acceptChanges, BooleanmodifyProperties) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityStateentityState, Boolean acceptChanges, Boolean modifyProperties,Nullable`1 forceStateWhenUnknownKey) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1node) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1node, Func`2 handleNode) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1node, Func`2 handleNode) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1node, Func`2 handleNode) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1node, Func`2 handleNode) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntryrootEntry, EntityState targetState, EntityStatestoreGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey) at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.SetEntityState(InternalEntityEntryentry, EntityState entityState) at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Update(TEntity entity) at DAL.Repositories.TendersRepository.<UpdateTender>d__10.MoveNext() in C:\Progetti\DAL\Repositories\TendersRepository.cs:line 613 at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at UI.Controllers.TenderController.<SelectTenderWinner>d__13.MoveNext() in C:\Progetti\UI\Controllers\TenderController.cs:line 808 This exception was originally thrown at this call stack: [External Code] DAL.Repositories.TendersRepository.UpdateTender(ML.Models.Tender) in TendersRepository.cs [External Code] UI.Controllers.TenderController.SelectTenderWinner(int,int, bool) in TenderController.cs
I don't understand why I'm getting this tracking error. I have disabled all tracking behavior of the constructor of the DBContext
base.ChangeTracker.AutoDetectChangesEnabled = false;
base.ChangeTracker.LazyLoadingEnabled = false;
base.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
I'm also using AsNoTracking() in all my queries. I can't figure out why EF core is tracking anyway.
The entity_one is "Tender", the entity_two is "TenderOffer"
This is the code in the controller:
try
{
//id and winnerOfferID are parameters of the request
Tender tender = await this._tenderRepository.GetTender(id, false, this.CurrentCompanyID);
TenderOffer offer = tender.TenderOffers.FirstOrDefault(o => o.ID == winnerOfferID)
tender.IsClosed = true;
tender.ClosureDate = DateTime.UtcNow;
tender.ShowWinner = showWinner;
tender.WinnerOfferID = winnerOfferID;
tender.TenderOffers.ForEach(o =>
{
if (o.ID == winnerOfferID)
{
o.Status = TenderOfferStatus.Winner;
}
else
{
o.Status = TenderOfferStatus.Rejected;
o.Company = null;
}
});
await this._tenderRepository.UpdateTender(tender);
return Ok();
}
catch (Exception ex)
{
return StatusCode(500);
}
This is the Update function:
public async Task<Tender> UpdateTender(Tender tender)
{
if (tender == null || tender.ID <= 0)
throw new ArgumentNullException("Cannot update, tender is null");
this._context.Tenders.Update(tender);
await this.SaveChangesAsync();
return tender;
}
This is the Get function:
public async Task<Tender> GetTender(int id, bool skipCompanyCheck = false, int? companyId = null)
{
IQueryable<Tender> query = this._context.Tenders.AsNoTracking()
.Include(t => t.Company).AsNoTracking()
.Include(t => t.Company).ThenInclude(c => c.Logo).AsNoTracking();
//Other include based on parameters, ALSO TENDER OFFERS
tender = await query.Where(tender => tender.ID == id).FirstOrDefaultAsync();
return tender;
}