所以我遇到的问题如下。当进入这个if语句时,我想从InstallationBOM表中删除所有带有ClearDbInstallForGroupAndHeader()的条目。然后我想把NewInstallationBoms中的所有条目添加到我的InstallationBOM表中,同时计算总成本,但当我想用这行添加它时db.InstallationBOM.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 + "nn" + 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 + "nn" + 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);
}
}
问题是NewInstallationBoms
附加在上下文中。但是您尝试将它们添加到AddInstallToDbCalcTotalCost
中的另一个上下文中。
解决方案1:您应该使用相同的上下文。详细答案
解决方案2:您应该首先在第一个上下文中分离它们,然后在第二个上下文中附加它们。详细答案。
解决方案3(归功于grek40):如果您在第一个上下文中使用AsNoTracking()
。它将不会被跟踪/缓存。因此,您可以在第二个上下文中安全地使用它。
在你的建议中,最好遵循解决方案1。如果使用依赖注入容器,则可以根据请求创建dbcontext。除此之外,您可以在上层管理dbcontext的生存期,也可以使您的类是可丢弃的,并管理类中的dbcontext。