Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework "An entity object cannot be referenced by multiple instances of IEntityChangeTracker"

I am getting the error

An entity object cannot be referenced by multiple instances of IEntityChangeTracker

when trying to create a new entity and save it to the DB.

I understand the error and how it normally occurs, but in this instance all I am doing is creating a new entity and adding a few ints to it before saving, not adding any other entities from other contexts.

I have included the function that is causing the error. As you can see it is being passed an EndProduct which is an entity which is being tracked by a different context to the one in the _billableRepository, but since I am not trying to in anyway assign that entity to the newly created billable I don't see how it can be a problem.

The only way I can see the error happening is because a couple of the int values that are being assigned to the new Billable are taken from the existing EndProduct that is being tracked by a different context, but surely the IEntityChangeTracker doesn't track the individual primitives of an entity?

public void AddBillable(EndProduct endProduct, int? purchaseId, string centreCode, int userId)
{
    if (endProduct.Product != null)
    {
        var existingBillableForUserForProductId = _billableRepository.GetQuery(b => b.UserId == userId && b.ProductId == endProduct.ProductId);
        if (endProduct.BillablePartId != null && !existingBillableForUserForProductId.Any())
        {
            var billable = new Billable {
                ProductId = endProduct.ProductId.Value, //int
                UserId = userId, //int
                PartId = endProduct.BillablePartId.Value, //int
                DateAdded = DateTime.UtcNow, //datetime
                PurchaseId = purchaseId, //int 
                CentreCode = centreCode //string
            };

            _billableRepository.Add(billable); //error here
            _billableRepository.UnitOfWork.SaveChanges();
        }
    }
}
like image 411
Anduril Avatar asked Jun 23 '16 11:06

Anduril


3 Answers

The most likely cause of this is to do with any dependency injection tool you're using.

There should only be one DbContext in play per unit of work. If you are newing up a new one each time, make sure the old one is disposed of.

Otherwise, you will have multiple instances of the same context running alongside each other.

This is where the change tracker gets confused and is unable to track changes to your entities.

like image 124
Derek Avatar answered Nov 11 '22 20:11

Derek


On your model (GetById method) try to put something like this:

var billable = _db.Billable.AsNoTracking().SingleOrDefault(i => i.BillableId == id);

Use AsNoTracking() so that it returns a new query where the entities will not be cached in the System.Data.Entity.DbContext

like image 29
John Philip Mayordo Avatar answered Nov 11 '22 19:11

John Philip Mayordo


You can fix by attaching your entity in the repository. Like this:

_context.Set<T>.Attach(entity)

Where Set its your DbSet in the context.

like image 24
Dmitriy Kovalenko Avatar answered Nov 11 '22 19:11

Dmitriy Kovalenko