ASP.NET MVC3和实体错误框架v4.1的实体对象不能被IEntityChangeTracke

2019-07-31 04:47发布

目前,用户将产品添加到我的购物车的时候我的添加操作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);
    }

Answer 1:

当你把车到会话,你从分离这方面的目标? 实体对象将携带上下文和他们在一起,所以你需要明确之前将其卸下。



文章来源: ASP.NET MVC3 and Entity Framework v4.1 with error An entity object cannot be referenced by multiple instances of IEntityChangeTracker