【问题标题】:Understanding the exception "An entity object cannot be referenced by multiple instances of IEntityChangeTracker."了解异常“IEntityChangeTracker 的多个实例无法引用实体对象”。
【发布时间】:2015-07-18 14:37:53
【问题描述】:

我正在做一个我应该制作电子书店的项目。这是一个实体关系模型,我使用它在 SQL Server 中生成了一个数据库。

现在,在使用以下代码生成账单时,我在为我的实体关系模型调用 SaveChanges() 方法时遇到了 An entity object cannot be referenced by multiple instances of IEntityChangeTracker. 异常,(ebs)

这里是代码。 我在会话中维护购物车。此外,用户 ID 也保留在会话中。

List<Title> cartItems = (List<Title>)Session["eStoreCart"];
int userid = Int32.Parse(Session["eStoreUserId"].ToString());
User us = ebs.Users.SingleOrDefault(u => u.UserId == userid);
Bill bl = new Bill();
bl.BillAmount = Decimal.Parse(lblBill.Text);
bl.BillDate = DateTime.Now;
foreach (Title item in cartItems)
{
    bl.Titles.Add(item);
}
us.Bills.Add(bl);
ebs.SaveChanges();
Response.Redirect("Orders.aspx");

我对 Entity Framework 和 LINQ 完全陌生。因此,任何帮助解释正在发生的事情以及解决方法将不胜感激。

【问题讨论】:

  • 您是否在using 块内访问ebs,如下所示:using (var ebs = new MyEntities()) { ... }
  • 不,我不是。这是单个Button 控件下的代码。

标签: c# linq entity-framework exception


【解决方案1】:

看起来您可能正在创建 DbContext ebs 作为实例变量并保留它。相反,您应该考虑轻量级实体上下文并按需创建它们,即每次您需要查询或修改数据存储时,尤其是在 Web 应用程序中使用它之后。

请查看以下文档:Working with DbContextAdd/Attach and Entity States

具体来说,请注意:

使用 Web 应用程序时,请使用每个上下文实例 请求。

所以不要保留一个长时间运行的DbContext:当你想修改你的数据存储时,而是在using 块中创建一个新的。 DbContext 非常轻巧,因此您可以按需构建和拆除它们。

另见this answer

现在,至于例外:我预计这是由于您在会话中存储的Title 对象:这些对象必须是在另一个DbContext 中创建的。您可以尝试将它们附加到新的DbContext(查看上面链接的文档)。但另一种方法:不要在会话中保留 Title 对象,而是保留这些对象的 ID,然后在新的 DbContext 中再次查找它们。

类似这样的:

在您的情况下,代码可能如下所示:

List<int> cartItemIds = (List<int>)Session["eStoreCart"];
int userid = Int32.Parse(Session["eStoreUserId"].ToString());

using (var ebs = new MyDbContext())
{
    User us = ebs.Users.SingleOrDefault(u => u.UserId == userid);
    Title title = null;
    Bill bl = new Bill();

    bl.BillAmount = Decimal.Parse(lblBill.Text);
    bl.BillDate = DateTime.Now;

    foreach (var id in cartItems)
    {
        title = ebs.Titles.Where(t => t.Id == id);
        bl.Titles.Add(title);
    }

    us.Bills.Add(bl);
    ebs.SaveChanges();
}

Response.Redirect("Orders.aspx");

另一个提示:查看 ASP Membership API 以获得一些额外的 webapp 用户支持。您可能不需要进行太多更改,并且您将获得一些 API 来执行密码策略/过期/更改等操作。

【讨论】:

  • 我使用了这段代码,我所做的唯一更改是` using (eBookStoreDBModelContainer ebs = new eBookStoreDBModelContainer())` 这实际上在ebs.SaveChanges(); 行中给出了相同的错误。
  • Rangan:您还有其他未打开的上下文吗?
  • 我想是的。我有一个全局声明的eBookStoreDBModel ebs,在Page_Load 上,我有ebs = new eBookStoreDBModel。我只在整个页面中都使用了它,它在所有页面中都可以正常工作,除了这个。
  • 感谢您的帮助。我不得不摆弄一下,这段代码有效。 ` foreach (cartItems 中的标题项目) { bl.Titles.Add(ebs.Titles.SingleOrDefault(ttl => ttl.TitleId == item.TitleId)); } `
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 2016-07-08
  • 1970-01-01
相关资源
最近更新 更多