Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity framework's invalid operation exception "An entity object cannot be referenced by multiple instances of IEntityChangeTracker"

I'm running into a rather perplexing "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" error with Entity framework 6, and though it is easy enough to resolve this by implementing a simple workaround, the point is that original implementation should work as is. Here's the way the relevant classes look

public class Response
{
    public int Id { get; set; }

    public string QuestionId { get; set; } 
//foreign key
    public int UserId { get; set; }
    public virtual User User { get; set; }

    public bool IsDeleted { get; set; }
}

public class User
{
    public int Id { get; set; }

    public string UserName {get; set;}
    public virtual List<Response> Responses { get; set; }

    public bool IsDeleted { get; set; }
}

And, the relevant code to update the responses is as follows

/* 1 */ using (var db = new SomeContext())
/* 2 */ {
/* 3 */       var existingResponses = userResponses.Select(userResponse =>
/* 3 */                db.Responses.FirstOrDefault(
/* 3 */                r => r.QuestionId.Equals("1.1.1") 
/* 3 */                && r.User.Id.Equals(user.Id) && !r.IsDeleted))
/* 3 */                .Where(existingResponse => existingResponse != null).ToList();
/* 4 */       if (existingResponses.Any())
/* 5 */       {
/* 6 */            foreach (var response in existingResponses)
/* 7 */            {
/* 8 */                 response.IsDeleted = true;
/* 9 */            }
/* 10 */       }

/* 11 */     var newResponses = new List<Response>()
/* 12 */     {
/* 13 */         new Response()
/* 14 */         {
/* 15 */            QuestionId = "1.1.1",
/* 16 */            User = user,
/* 17 */            //UserId = user.Id,
/* 18 */          }
/* 19 */     };

/* 20 */     newResponses.ForEach(r => db.Responses.Add(r));

/* 21 */      db.SaveChanges();

The code above is simple enough; I first update an existing record and set its IsDeleted to true and then add new record(s), in this specific example response record with QuestionId == "1.1.1" is first updated and then a new responses record with QuestionId == "1.1.1" is inserted. If I comment out line 16 and uncomment line 17 then all works well but the moment the code is executed as shown above I get an "invalid operation exception "An entity object cannot be referenced by multiple instances of IEntityChangeTracker". The user exists in the User table and is retrieved as so

var user = _db.Users.FirstOrDefault(r => r.UserName.Equals("[email protected]"));

I have looked at a few related questions on stackoverflow here and here, and though the work around works my question is that surely this is a bug in EF6 itself. I should not have to bother with Ids and should be able to simply assign an object as per line 16 above, that is the whole purpose of an ORM.

And, as a corollary if this is a bug then should I always take the route of using code in line 17?

like image 666
Sangeet Agarwal Avatar asked Jan 12 '23 14:01

Sangeet Agarwal


1 Answers

Each entity has link to DBContext that was used for it's creation. And entity from one DBContext can't be used with another DBContext, so you need to detach it from original DBContext and attach to new one, or use the same DBContext.

like image 132
Sergey Litvinov Avatar answered Jan 17 '23 16:01

Sergey Litvinov