dbContext IEntityChangeTracker的多个实例无法引用实体对象

时间:2016-04-06 12:29:25

标签: c# entity-framework dbcontext

所以我遇到的问题如下。进入这个if语句时,我想从表InstallationBOM中删除ClearDbInstallForGroupAndHeader()的所有条目。然后我想将NewInstallationBoms中的所有条目添加到我的InstallationBOM表中,同时计算总成本,但是当我想用这行 db.InstallationBOMs.Add(newInstallationBom); 添加它时,我得到以下错误:
     IEntityChangeTracker的多个实例无法引用实体对象。

 if (InstallationSelected)
 {
      bool newEntry = true;
      if (SelectedQuoteDetails != null)
      {
          QuoteDetail theQuoteDetail = SelectedQuoteDetails.FirstOrDefault(X => X.GroupNr == groupID && X.LineType == "I");
          if (theQuoteDetail != null)
          {
               this.ClearDbInstallForGroupAndHeader();
               int position = SelectedQuoteDetails.IndexOf(theQuoteDetail);
               newEntry = false;
               theQuoteDetail.Quantity = InstallQty;
               theQuoteDetail.UnitCost = InstallCost;
               theQuoteDetail.UnitPrice = InstallPrice;
               SelectedQuoteDetails[position] = theQuoteDetail;

               db.QuoteDetails.Attach(theQuoteDetail);
               db.Entry(theQuoteDetail).State = EntityState.Modified;
               db.SaveChanges();

              decimal totalInstallationCost = 0;
              totalInstallationCost = AddInstallToDbCalcTotalCost(theQuoteDetail.Line.Value, groupID);

              newLines.UnitCost = totalInstallationCost;
              newLines.UnitPrice = newLines.UnitCost * (1 + (Settings.MarginPercentage / 100));

              InstallCost = newLines.UnitCost ?? 0;
              InstallPrice = newLines.UnitPrice ?? 0;                                        

              RaisePropertyChanged(() => SelectedQuoteDetails);

          }
      }
  }

  public void ClearDbInstallForGroupAndHeader()
    {
        try
        {
            using (QuoteConfiguratorEntities db = Utilities.GetContext())
            {
                List<InstallationBOM> dbList = db.InstallationBOMs.Where(x => x.QuoteHeaderId == this.SelectedQuoteHeader.ID && x.GroupNr == this.SelectedGroup.ID)
                                                        .ToList();
                foreach (InstallationBOM existingInstallationBom in dbList)
                {
                    db.InstallationBOMs.Remove(existingInstallationBom);
                }
                db.SaveChanges();
            }

        }
        catch (Exception ex)
        {
            this.Message = ex.Message + "\n\n" + ex.StackTrace;
            this.ShowErrorMessage();
        }
    }

    public decimal AddInstallToDbCalcTotalCost(decimal pLine, long pGroupNr)
    {
        decimal totalInstallationCost = 0;
        try
        {
            using (QuoteConfiguratorEntities db = Utilities.GetContext())
            {
                foreach (InstallationBOM newInstallationBom in this.NewInstallationBoms)
                {
                    newInstallationBom.QuoteHeaderId = this.SelectedQuoteHeader.ID;
                    newInstallationBom.GroupNr = pGroupNr;
                    newInstallationBom.LineNumber = pLine;
                    totalInstallationCost += (newInstallationBom.Quantity.Value *
                                              newInstallationBom.Cost.Value);
                    db.InstallationBOMs.Add(newInstallationBom);                       
                    db.SaveChanges();   
                }
            }
        }
        catch (Exception ex)
        {
            this.Message = ex.Message + "\n\n" + ex.StackTrace;
            this.ShowErrorMessage();
        }
        return totalInstallationCost;
    }

public void OpenInstallationOptionsWindow(bool AsThread = false)
    {
        try
        {
            if (AsThread)
            {
                this.Busy = true;
                this._Thread = new Thread(() => QuoteConfiguratorViewModel.OpenInstallationOptionsWindow(this));
                this._Thread.IsBackground = true;
                this._Thread.Start();
            }
            else
            {
                using (QuoteConfiguratorEntities db = Utilities.GetContext())
                {
                    ObservableCollection<InstallationBOM> installBomListGroup = new ObservableCollection<InstallationBOM>(db.InstallationBOMs.Where(x => x.QuoteHeaderId == this.SelectedQuoteHeader.ID
                        && x.GroupNr == this.SelectedGroup.ID).ToList());
                    if (installBomListGroup != null)
                    {
                        if (!installBomListGroup.Any())
                        {
                            ClearInstallationBomEntry();
                            NewInstallationBoms = new ObservableCollection<InstallationBOM>();
                        }
                        else if (installBomListGroup.Any())
                        {
                            NewInstallationBoms = installBomListGroup;
                        }
                    }                        

                    Messenger.Default.Send<OpenInstallationWindow>(new OpenInstallationWindow());

                }

            }
        }
        catch (Exception ex)
        {
            this.Message = Utilities.GetError(ex);
        }
    }

1 个答案:

答案 0 :(得分:2)

问题是NewInstallationBoms附加在上下文中。但您尝试在AddInstallToDbCalcTotalCost

中的另一个上下文中添加它们

解决方案1:您应该使用相同的上下文。详细answer

解决方案2:您应该首先在第一个上下文中分离它们并将它们附加到第二个上下文中。详细answer

解决方案3(致grek40的积分):如果您在第一个上下文中使用AsNoTracking()。它不会被跟踪/缓存。因此,您可以在第二种情况下安全地使用它。

在你的讨论中,最好遵循解决方案1.如果使用依赖注入容器,则可以根据请求创建dbcontext。 除此之外,您可以在较高级别管理dbcontext的生命周期,或者您可以使您的类处于一次性状态并在您的类中管理数据库上下文。