我在WCF客户端 - 服务器应用程序中使用self-tracking个实体。我的WCF服务返回各种实体,可以使用相应的Update方法更新这些实体。
这种方法运作良好,但现在我遇到了问题。为了保持关注,我将这个讨论局限于一个特定的案例,简化为基本要素。
我的一个表称为SystemDefinition。它没有外键,但另一个表(Route)有一个外键。因此,它在实体模型中具有单个导航属性(称为路径)。所有其他列都是标量。该表和相应的实体有一个名为Id的主键列,类型为Guid。该数据库是SQL Server Compact v3.5。
为了重现这个问题,我可以:
UpdateSystem()中的代码很简单(为了清晰起见,删除了非基本代码):
_objectContext.SystemDefinitions.ApplyChanges(system);
_objectContext.SaveChanges();
检索实体时没有Include()子句,这意味着Routes集合为空(无论如何,如果Route中没有带有SystemDefinition外键的行,则仍会出现错误)。因此,我传递给Update方法的SystemDefinition实体是图中的唯一实体。然而,我仍然得到以下例外:
InvalidOperationException异常: AcceptChanges无法继续,因为 对象的键值与之冲突 另一个对象 ObjectStateManager。确保 密钥值在调用之前是唯一的 的AcceptChanges。
第一个方法调用(ApplyChanges)抛出异常。我确信ObjectContext是新鲜的,为每个方法调用创建一个新的。
我已经将代码一直调试到它抛出的位置(在ObjectContext.FixupKey()中),但代码对我来说没什么意义,并且Microsoft的源代码中没有注释来指示导致的条件是什么它实际上意味着。
当然,这条消息具有误导性?更新中只涉及一个实体。可能会发生什么?
PS。我找到了一个论坛帖子,建议覆盖实体类的GetHashCode()和Equals()方法可能会有所帮助。如果错误是由ObjectStateManager无法确定要更新的实体实际上与上下文中的某个实体相同,则会有一定意义。我尝试了(使用部分类),但不幸的是它没有帮助。所以现在我迷路了。任何建议都会受到欢迎。
答案 0 :(得分:1)
我怀疑您的_objectContext
已经包含您尝试应用更改的实体实例。由于您的实体是从外部客户端接收的,因此它们将永远不会与上下文已经知道的那些实例相同(就实例引用而言)。
抛出异常时这是有意义的:上下文最终会有两个包含相同键值的不同实例。
要解决此问题,您只需确保始终使用新的上下文。