从对象上下文中分离实体

时间:2012-01-03 11:37:52

标签: asp.net-mvc asp.net-mvc-3 entity-framework

在我的模型中,我有两个类别和产品。他们之间存在着许多关系。我正在使用实体框架的代码优先方法。 我正在尝试创建一个编辑类别和产品之间映射的函数,但是我收到了一个错误。

  

实体对象不能被多个实例引用   IEntityChangeTracker。

我发现在实体框架中关闭连接后,实体仍在跟踪 所以我假设我必须从ObjectContext手动分离实体,但我的解决方案不起作用。这是我的控制器代码

public ActionResult Edit(int id)
    {
        Product product = db.Products.Find(id);
        ViewData["categories"] = _categories.GetAllCategories();
        ViewBag.CompanyID = new SelectList(db.Companies, "CompanyID", "Name", product.CompanyID);
        return View(product);
    }

    [HttpPost]
    public ActionResult Edit(FormCollection collection, Product product)
    {
        if (ModelState.IsValid)
        {
            _product.UpdateProduct(product);
            _product.EditMappingProductCategories(collection, product.ProductID);
            return RedirectToAction("ProductsList");
        }
        ViewBag.CompanyID = new SelectList(db.Companies, "CompanyID", "Name", product.CompanyID);
        ViewData["categories"] = _categories.GetAllCategories();
        return View(product);
    }

我的服务层功能。我从表单收集新的类别,并根据结果我编辑产品。

public void EditMappingProductCategories(FormCollection collection , int pro) 
    {
        using (EFDbContext context = new EFDbContext())
        {
            List<Category> list = new List<Category>();
            Product product = context.Products.Single(m => m.ProductID == pro);
            foreach (var item in collection.AllKeys)
            {
                if(collection[item].Contains("true"))
                    list.Add(context.Categories.Find(Convert.ToInt32(item)));
            }
            //Check if produkt contains marked category in formCollection
            foreach (var item in list)
            {
                if (product.Categories.Contains(item))
                {
                    product.Categories.Add(item);
                    context.Entry(item).State = EntityState.Detached;
                }
            }
            context.SaveChanges();
            //Check if product contains categories which are not marked in formCollection
            foreach (var item in product.Categories)
            {
                if (list.Contains(item))
                    product.Categories.Remove(item);
            }
            context.SaveChanges();
            UpdateProduct(product);
        }
    }
    public void UpdateProduct(Product product) 
    {
        using (EFDbContext context = new EFDbContext())
        {
            context.Entry(product).State = EntityState.Modified;
            context.SaveChanges();
            context.Entry(product).State = EntityState.Detached;
        }
    }

问题在于我不知道哪些实体仍在跟踪。有没有检查的情况?在调试模式还是其他?


非常感谢你的解决方案。我不知道这个功能。我做了这个改变,错误消失但我有其他问题。我在更新功能中将产品附加到上下文但我的类别没有更新。所以我手动修改所有类别的状态,当我在调试器中观看saveChanges()函数之前,我看到所有这些类别都被标记为已修改。 但是我的数据库中没有更新类别和产品之间的映射。 更新功能代码

public void UpdateProduct(Product product) 
        {
            using (EFDbContext context = new EFDbContext())
            {
                context.Products.Attach(product);
                if (product.Categories != null)
                {
                    foreach (var item in product.Categories)
                    {
                        context.Entry(item).State = EntityState.Modified;
                    }
                }
                context.Entry(product).State = EntityState.Modified;

                context.SaveChanges();
            }
        }

1 个答案:

答案 0 :(得分:9)

您收到此错误的原因是每次有using (EFDbContext context = new EFDbContext)时,实体都会专门附加到该上下文。如果您从一个上下文中读取实体,然后尝试将它们附加到另一个上下文以进行更新,您将收到EF无法在多个上下文中跟踪实体的错误。

在您从上下文中读取实体时尝试此操作:

context.Products.AsNoTracking().Single(m => m.ProductID == pro);

通过调用AsNoTracking(),您将确保返回的权利不会附加到任何上下文。然后,您可以在更新/保存操作期间将其附加到另一个上下文。