【问题标题】:SaveChangesAsync fails and callback not executed (IdeaBlade)SaveChangesAsync 失败且未执行回调 (IdeaBlade)
【发布时间】:2014-06-09 20:37:07
【问题描述】:

我从 DevForce 2010 版本 6.1.15.0 继承了一个使用 IdeaBlade 在 Silverlight 4 上构建的应用程序。后端数据库是 SQL Server 2008。在跟踪一些不起作用的更新/插入时,我发现我在调用 IdeaBlade.EntityModel.EntityManager.SaveChangesAsync() 时收到以下错误。

“提供的实体列表中缺少一个或多个包含引用的临时 ID 的实体。缺少的实体包括:修订:-100。有关更多详细信息,请参阅异常成员”

额外的挖掘发现了以下额外信息。

“UPDATE 语句与 FOREIGN KEY 约束“FK_valuation_revision”冲突。冲突发生在数据库“XX”、表“Revision”、列“RevisionID”中。该语句已终止。”

在深入挖掘中,我发现了以下内容:

  1. 涉及的两个主要类别是:估值和修订
  2. Valuation 有一系列修订。在数据库中,这由引用 Valuation 表的 PK 的 Revision 表(非空)上的 FK 表示。
  3. 此外,Valuation 还引用了 CurrentRevision。这在数据库中表示为 Valuation 表上的 FK(如果没有修订,则可以为 null),它引用 Revision 表上的 PK。
  4. 在问题代码中,创建了一个新的 Revision 对象,如下所示:

    myNewRevision = new Revision { Valuation = myExistingValuation };

    此时,myNewRevision 是一个 IdeaBlade.EntityModel.Entity,EntityState 为“Added”。

  5. 对对象进行几次额外更改后,将执行以下代码。

    EntityManager.AddEntity(myNewRevision);

    上面对 AddEntity 的调用似乎没有完成任何事情,因为调用后 MyNewRevision 的状态与调用前的状态相同。

  6. 接下来尝试保存新创建的 Revision 对象。

    SaveChangesAsync(new[] { myNewRevision }, null, RevisionCallback, null);

    上面的语句在 try...catch 块中并且没有抛出错误,但是 RevisionCallback 例程永远不会被执行。此外,myNewRevision 的 EntityState 仍为“已添加”,密钥仍显示为 -100。

  7. 然后,现有的 Valuation 对象会使用对新版本的引用进行更新。

    myExistingValuation.CurrentRevision = myNewRevision;

    这会导致 myExistingValuation 的 EntityState 从“未更改”更改为“已修改”。

  8. 最后,代码尝试保存对 Valuation 对象的更改。

    SaveChangesAsync(new[] { myExistingValuation }, null, ValuationCallback, null);

  9. 此调用的结果是调用了 ValuationCallback,但 myExistingValuation 仍显示为“Modified”,对 myExistingValuation.CurrentRevision 的引用仍引用键为 -100 且 EntityState 为“Added”的 myNewRevision。回调方法返回的EntitySaveOperation对象有Exception == null,HasError = true,错误就是本题开头描述的那个。也就是说,

    “提供的实体列表中缺少一个或多个包含引用的临时 ID 的实体。缺少的实体包括:修订:-100。有关更多详细信息,请参阅异常成员”

    “UPDATE 语句与 FOREIGN KEY 约束“FK_valuation_revision”冲突。冲突发生在数据库“XX”、表“Revision”、列“RevisionID”中。该语句已终止。”

    数据库未更新。

有什么建议吗?为什么不执行第一次调用 SaveChangesAsync 的回调例程?如何使更新正常工作?

【问题讨论】:

    标签: entity-framework devforce


    【解决方案1】:

    没有调用 RevisionCallback 很奇怪,但是当您执行后续步骤时,异步方法可能尚未完成。

    这里的异步方法不能使用 try/catch,因为 DevForce 2010 不使用更新的基于任务的异步模式;因此异常将返回到您的回调或完成处理程序,或者如果为 EntityManager 设置了一个,则可能返回到 EntityServerError 处理程序。

    默认情况下,DevForce 会将所有对实体的更改保存在缓存中,除非您指定保存列表,但该列表不必仅包含一项。当您保存具有临时 ID 的实体时,所有具有临时 PK 或 FK 的实体都需要位于传递给 SaveChangesAsync 的保存列表中。保存成功后,DevForce 将自动处理对 FK 的修复。

    您是否有任何理由不能执行以下操作:

    myNewRevision = new Revision { Valuation = myExistingValuation };
    myExistingValuation.CurrentRevision = myNewRevision; 
    SaveChangesAsync(ValuationCallback);
    

    【讨论】:

    • 您好,金,感谢您的回复。我按照建议进行了尝试,但出现以下错误。 “UPDATE 语句与 FOREIGN KEY 约束“FK_valuation_revision”冲突。冲突发生在数据库“XX”、表“Revision”、列“RevisionID”中。该语句已终止。” (原来这个错误也发生在未更改的版本中,所以我会相应地更新原始问题。)
    • 那么我想问题是为什么没有保存修订版,并且从未调用过回调。我从未见过不调用回调的情况。您是否在客户端或服务器上有可能干扰保存的 EntityServerSaveInterceptor 处理程序?
    • 有一个EntityServerSaveInterceptor,但它所做的只是调用ExecuteSave上的基函数并返回结果,所以它并没有真正做任何事情。我现在用它来做一些调试。我想知道这个特定版本的 IdeaBlade 是否存在错误...
    • 我们从未见过没有调用回调的问题,所以这不是在最新的 6.1.16 版本中修复的问题。在保存拦截器中调试时,还要查看验证是否通过,并且所有 PK 和 FK 属性在执行保存之前都包含正确的临时 ID。你可以在drc.ideablade.com/xwiki/bin/view/Documentation/…找到更多关于拦截器的信息。
    • 谢谢!我得到了你的帮助,金。您说修复 FK 需要同时保存对象,并且您将我指向 EntityServerSaveInterceptor。这是一个时间问题。对 Valuation 对象进行了较早的更改,并且仅在该对象上调用了 SaveChangesAsync。然后创建 Revision 对象,将其添加到 Valuation 对象中,并再次调用 SaveChangesAsync。由于是异步的,第一次调用直到第二次更改之后才执行。它试图在对修订版进行 FK 后仅更新估值。 Revision 的回调没有发生,因为它还没有保存。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 2018-04-18
    相关资源
    最近更新 更多