3

我在 WCF 客户端-服务器应用程序中使用自跟踪实体。我的 WCF 服务返回各种实体,这些实体可以使用相应的 Update 方法进行更新。

这工作了一段时间,但现在我遇到了问题。为了保持重点,我将把这个讨论限制在一个特定的案例中,简化为最基本的内容。

我的一张表称为 SystemDefinition。它没有外键,但另一个表(Route)有一个外键。因此,它在实体模型中有一个导航属性(称为 Routes)。所有其他列都是标量。该表和相应的实体有一个名为 Id 的主键列,类型为 Guid。该数据库是 SQL Server Compact v3.5。

要重现该问题,我可以:

  1. 使用我的 WCF 服务的 GetSystem() 方法检索单个 SystemDefinition 实体
  2. 在客户端中,在实体上调用 MarkAsDeleted()
  3. 调用 UpdateSystem(),将实体作为参数传递

UpdateSystem() 中的代码很简单(为了清楚起见,删除了非必要代码):

_objectContext.SystemDefinitions.ApplyChanges(system);
_objectContext.SaveChanges();

该实体是在没有 Include() 子句的情况下检索的,这意味着 Routes 集合为空(无论如何,如果 Route 中没有具有 SystemDefinition 外键的行,则仍然会发生错误)。所以我传递给 Update 方法的 SystemDefinition 实体是图中唯一的实体。但是我仍然遇到以下异常:

InvalidOperationException:AcceptChanges 无法继续,因为对象的键值与 ObjectStateManager 中的另一个对象冲突。在调用 AcceptChanges 之前确保键值是唯一的。

异常由第一个方法调用 (ApplyChanges) 引发。我确定 ObjectContext 是新鲜的,为每个方法调用创建一个新的。

我已经将代码一直调试到它抛出的位置(在 ObjectContext.FixupKey() 中),但代码对我来说意义不大,并且微软的源代码中没有注释来说明导致它的条件实际上意味着什么.

当然,该消息具有误导性?更新中只涉及一个实体。可能会发生什么?

PS。我发现一个论坛帖子建议覆盖实体类上的 GetHashCode() 和 Equals() 方法可能会有所帮助。如果错误是由于 ObjectStateManager 无法确定要更新的实体实际上与上下文中的某个实体相同,那么这将是有道理的。我试过了(使用部分类),但不幸的是它没有帮助。所以现在我迷路了。欢迎大家提出意见。

4

1 回答 1

1

我怀疑您_objectContext已经包含您尝试从中应用更改的实体实例。由于您的实体是从外部客户端接收的,因此它们永远不会与上下文已经知道的那些实例相同(就实例引用而言)。

这对于抛出的异常是有意义的:上下文以两个包含相同键值的不同实例结束。

要解决这个问题,您只需确保始终使用新的上下文。

于 2010-10-11T09:01:35.527 回答