我目前正在运行一个应用程序,该应用程序有一个非常长的Linq事务。所有的事情都必须发生在这个事务中,我不确定对象是否或在哪里相互干扰。
当我试图保存更改时,我看到出现以下警告:
System.InvalidOperationException:对数据库的更改为已成功提交,但在更新时出错对象上下文。ObjectContext可能处于不一致的状态。内部异常消息:AcceptChanges无法继续,因为对象的键值与中的另一个对象冲突ObjectStateManager。之前请确保关键值是唯一的调用AcceptChanges。
从我在谷歌上看到的内容来看,人们发现了很多一次性的解决方案(很少与冲突的密钥有关),而且他们通常不会发布消息(当然,总比什么都没有好)。
我不清楚的是如何找出这个问题的原因?
我在不同的地方更新了很多记录,让它们超出了范围。我猜.NET编译器知道如何在不让它们通过GC的情况下跟踪这些对象,这样它就可以在最后提交所有内容。所有的更改似乎都会在数据库的后记中结束。
示例:
// create new A, SA for new incoming tasks
SF_SUB_AREA sa = null;
SF_AREA a = null;
if (isNewSA) // new SA
{
areaID = MakeSalesForceGUID();
a = new SF_AREA
{
ID = areaID,
DESCRIPTION = t.DESCRIPTION,
CU_NUMBER = Convert.ToString(t.CU_NUMBER),
FC = t.FC,
PROJECT = cp.ID,
DELETE_FLAG = "I"
};
ctx.SF_AREA.AddObject(a);
SAID = MakeSalesForceGUID();
sa= new SF_SUB_AREA
{
ID = SAID,
PROJECT_REGION = t.CR,
AREA = areaID,
DELETE_FLAG = "I"
};
ctx.SF_SUB_AREA.AddObject(sa);
}
else // old SA
{
List<SF_AREA> lia = (from a2 in ctx.SF_AREA
join a2 in ctx.SF_SUB_AREA on a2.ID equals sa2.AREA
where sa2.ID == t.SUB_AREA
select ct2).ToList();
if ((lia != null) && (lia.Count > 0))
{
a = lia[0];
a.DELETE_FLAG = "U";
a.CLIENT_UNIT_NUMBER = Convert.ToString(t.CU_NUMBER);
a.DESCRIPTION = t.DESCRIPTION;
a.FC = t.FC;
a.PROJECT = cp.ID;
} // TODO: throw an error here for else block
List<SF_SUB_AREA> lisa = (from sa2 in ctx.SF_SUB_AREA
where sa2.ID == t.SUB_AREA
select sa2).ToList();
if ((lisa != null) && (lisa.Count > 0))
{
sa = lisa[0];
sa.PROJECT_REGION = t.AREA;
sa.AREA = lisa[0].AREA;
sa.DELETE_FLAG = "U";
}
}
...
ctx.SaveChanges(); // left out the try/catch
目前,我只是在每次提交东西时创建新的上下文,但我不知道这是否可取。
foreach (SF_MOVE_ORDER mo in liMO ) {
using (SFEntitiesRM ctx2 = new SFEntitiesRM()) // new context for every MO since it goes into an unknown state after every commit
{
List<SF_CLIENT_PROJECT> liCP = (from cp in ctx2.SF_CLIENT_PROJECT
where cp.ID == mo.CLIENT_PROJECT
select cp).ToList();
if ((liCP != null) && (liCP.Count > 0))
{
PerformMoveOrder(mo, liCP[0], ctx2);
}
}
}
通常出现这样的错误时,最好先保存一个对象,然后一次构建一个复杂的对象。这样,你就可以开始弄清楚问题出在哪里了。它最终可能会出现在对象图的某个位置,这是你甚至没有预料到的。但我不会继续把整个LINQ更新放在上下文中。将其分解为较小的保存,然后将其重建为较大的图形,您就会发现自己的错误。