Note that there are some explanatory texts on larger screens.

plurals
  1. POASP.NET MVC3 and Entity Framework v4.1 with error An entity object cannot be referenced by multiple instances of IEntityChangeTracker
    text
    copied!<p>Currently when adding a product to my cart the Add action of my <code>CartController</code> is called with the <code>orderEntryDisplayViewModel</code> (the order line object). </p> <pre><code> [HttpPost] public RedirectToRouteResult Add(Cart cart, OrderEntryDisplayViewModel orderLine) { if (!ModelState.IsValid) { return RedirectToAction("Display", "OrderEntry", new { Product = orderLine.Line.PartNum }); } CompleteProduct product = null; orderLine.Line.RequestedShipDate = orderLine.RequestedShipDate; if (orderLine.Line.NewMyPartNum != null) { orderLine.Line.MyPartNum = orderLine.Line.NewMyPartNum; } try { product = _inventoryRepo.FetchByPartNum(orderLine.Line.PartNum, User.Identity.Name); orderLine.Line.Product = product; cart.AddItem(orderLine.Line); //_cartRepo.Save(); } catch (DbUpdateException e) { throw; } catch { ModelState.AddModelError("", "Problem adding part to cart"); return RedirectToAction("Index", new { returnUrl = Url.Action("Index", "OrderEntry") }); } return RedirectToAction("Index", new { returnUrl = Url.Action("Index", "OrderEntry") }); } </code></pre> <p>Before it is reached the <code>CartModelBinder</code> either creates or gets the shopping cart from the session. </p> <pre><code>public class CartModelBinder : IModelBinder { private const string sessionKey = "Cart"; public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { CartRepository cartRepo = new CartRepository(); Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey]; if (cart == null) { cart = cartRepo.CreateCart(true); cartRepo.DetachCart(cart); controllerContext.HttpContext.Session[sessionKey] = cart; cartRepo.AttachCart(cart); } else { cartRepo.AttachCart(cart); } return cart; } } </code></pre> <p>If no cart currently exists in the session a new one is created though the <code>CartRepository</code> <code>CreateCart</code> method which then adds the newly created cart to the context. </p> <pre><code> public Cart CreateCart(bool saveCart = false) { Cart cart = new Cart(); context.Carts.Add(cart); if (saveCart) { context.SaveChanges(); } return cart; } </code></pre> <p>Before I add the cart object to the session I detach it from the context using <code>CartRepository</code> <code>DetachCart</code>, add it to the session, then attach it to the context again.</p> <pre><code>public void DetachCart(Cart cart) { ((IObjectContextAdapter)context).ObjectContext.Detach(cart); } </code></pre> <p>The <code>CartRepository</code> gets the context from <code>ContextHelper</code>:</p> <pre><code>public static class ContextHelper { public static InsideIIMAKContext InsideIIMAK { get { if (HttpContext.Current.Items["InsideIIMAKContext"] == null) { HttpContext.Current.Items.Add("InsideIIMAKContext", new InsideIIMAKContext()); } return (InsideIIMAKContext)HttpContext.Current.Items["InsideIIMAKContext"]; } } </code></pre> <p>If <code>CartModelBinder</code> finds a cart in the session then it attempts to attach the cart through the <code>CartRepsitory</code> method <code>AttachCart</code>.</p> <pre><code> public void AttachCart(Cart cart) { context.Carts.Attach(cart); } </code></pre> <p>At the end of the Add action in the <code>CartController</code> I redirect to the Index action to display the cart view. The index action requires the Cart object too so <code>CartModelBinder</code> is called a second time and this time calls the <code>CartRepository</code> <code>AttachCart</code> method. My error occurs at the <code>AttachCart</code> method </p> <blockquote> <p>"An entity object cannot be referenced by multiple instances of IEntityChangeTracker."</p> </blockquote> <p>I've researched this issue a good amount and it doesn't seem that I have a situation where I am adding the cart object to two instances of the context like seems to often be the reason for the error. It almost seems as if the cart object stored in the session is being modified with tracking information so when I try to attach it in the next HTTP request EF thinks it is attached to an active context, but really it's the context from the previous request. I found a forum which suggested I needed to detach the Entity Object before adding it to the session, but I've done that and still have the same issue.</p> <p>Hopefully I haven't missed anything in this explanation.</p> <p><strong>ANSWER</strong> Thanks to Mark Oreta</p> <pre><code> public void DetachCart(Cart cart) { var objectContext = ((IObjectContextAdapter)context).ObjectContext; objectContext.Detach(cart.Customer); foreach (var item in cart.Lines) { objectContext.Detach(item); } objectContext.Detach(cart); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload