【问题标题】:inconsistent context state不一致的上下文状态
【发布时间】:2012-07-27 15:35:57
【问题描述】:

我目前正在运行一个具有非常长的 Linq 事务的应用程序。一切都必须在这一事务中发生,我不确定对象是否或在何处相互干扰。

当我尝试保存更改时,我看到了这个警告:

System.InvalidOperationException:对数据库的更改是 提交成功,但更新时出错 对象上下文。 ObjectContext 可能处于不一致的状态。 内部异常消息:AcceptChanges 无法继续,因为 对象的键值与另一个对象冲突 对象状态管理器。确保键值在之前是唯一的 调用 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);
                    }
                }
            }

【问题讨论】:

  • 如果您发布代码可能会有所帮助。

标签: c# linq c#-4.0 linq-to-entities


【解决方案1】:

通常出现此类错误时,最好从保存一个对象开始,然后一次构建一个复杂对象。这样,您就可以开始找出问题所在。它最终可能会出现在您甚至没有预料到的对象图的某个位置。但我不会继续在上下文中抛出整个 LINQ 更新。将其分解为较小的保存并将其重建为最大图,您会发现错误。

【讨论】:

  • 完全应该想到这种方法。至于较小的节省……在这种情况下,这是业务需求。他们不想为混乱的部分提交买单。
  • 我相信 Josh 并不是建议您让生产代码使用较小的保存,只需在开发中使用较小的保存来定位此特定问题。
  • @ErikPhilips 没错。回溯到您的最终保存以用于生产,但在深度对象图中发现错误充其量是困难的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2015-07-08
  • 2022-06-14
  • 2020-04-06
  • 2018-01-20
相关资源
最近更新 更多