目前,用户将产品添加到我的购物车的时候我的添加操作CartController
时调用orderEntryDisplayViewModel
(命令行对象)。
[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") });
}
在到达之前, CartModelBinder
无论是创建或从会话中取得的购物车。
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;
}
}
如果没有车目前在会话存在一个新的虽然创建CartRepository
CreateCart
方法,然后将新创建的车到上下文。
public Cart CreateCart(bool saveCart = false)
{
Cart cart = new Cart();
context.Carts.Add(cart);
if (saveCart)
{ context.SaveChanges(); }
return cart;
}
在我的车对象添加到会话我把它从使用上下文CartRepository
DetachCart
,把它添加到会话,然后重新连接到上下文。
public void DetachCart(Cart cart)
{
((IObjectContextAdapter)context).ObjectContext.Detach(cart);
}
该CartRepository
会从上下文ContextHelper
:
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"];
}
}
如果CartModelBinder
发现在会议上车,然后它试图通过附加的车CartRepsitory
方法AttachCart
。
public void AttachCart(Cart cart)
{
context.Carts.Attach(cart);
}
在添加操作结束CartController
我重定向到Index操作来显示车查看。 该指数的行动需要太多所以车对象CartModelBinder
被称为第二次,这一次调用CartRepository
AttachCart
方法。 在发生我的错误AttachCart
方法
“实体对象不能由IEntityChangeTracker的多个实例被引用。”
我研究过这个问题,一个良好的金额,它似乎并不认为我在那里我加入购物车对象上下文的两个实例一样,似乎往往是错误的原因的情况。 它几乎好像存储在会话车对象被与跟踪信息,所以当我尝试将它连接在接下来的HTTP请求EF认为它是连接到一个活跃的背景下修改的,但实际上它是从以前的请求的上下文。 我发现了一个论坛,这表明我需要将它添加到会议之前分离的实体对象,但我做到了这一点,仍然有同样的问题。
希望我没有错过这个解释什么。
答案多亏了马克Oreta
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);
}