【发布时间】:2010-08-04 22:51:39
【问题描述】:
我有一些逻辑,需要克隆 POCO 实体图,为此我为每个 T4 生成的自跟踪实体创建了部分类,并在每个实体上实现了 ICloneable。每个实体都可以克隆自己,并在导航属性中遍历其所有子实体,并在每个子实体上调用 Clone(),然后最终返回其克隆的实例并添加其克隆的子实体。所以它是一个深度克隆并且工作正常。在克隆树中,所有实体都处于已添加状态,这是有道理的……因为克隆图是所有新实体。
克隆过程发生在实体上下文中的服务端,尽管克隆过程本身不进行数据访问,但克隆是在从数据库中新检索到的图上执行的(如果有更好的方法来克隆实体图随时通知我...)。
现在克隆的图形通过 WCF 传送到我们的 Silverlight 4 应用程序并显示在那里。用户可以立即保存或添加/修改此图中的数据,然后将其保存回服务没有问题,但是,如果他们从图中删除任何节点,这是一个问题。
当用户单击控件删除节点时,我通过调用 MarkAsDeleted() 来更改实体图。这适用于未更改的图表,但是对于我的所有内容都处于已添加状态的克隆图表,在保存回 WCF 服务中的数据库后,我得到了一个 OptimisicConcurrencyException。
“存储更新、插入或删除语句影响了意外数量的行 (0)。实体可能在加载实体后已被修改或删除。刷新 ObjectStateManager 条目。”
在我调用的服务中
context.EntitySetX.ApplyChanges(entityNodeInTree);
context.SaveChanges();
这一切都很好,除了在这种情况下。到目前为止,用户的解决方法是将克隆的图形保存回数据库,再次检索它(现在将全部保持不变),然后删除他们想要的任何数据,最后再次保存。
我不明白为什么会这样。是不是你不能 MarkAsDeleted 处于添加状态的东西?这对我来说没有任何意义,因为在使用我们的 Silverlight 应用程序期间,有时会同时添加项目然后从图表中删除项目,这不会导致问题。
有什么想法吗?
谢谢
【问题讨论】:
-
错误消息的含义与它所说的完全一样。跟踪 SQL。它没有按照框架的预期进行。查看 SQL 应该可以帮助您确定错误。
-
SQL Trace 没有用,因为没有生成 SQL。这是一个实体框架 STE 问题。在尝试将任何内容插入数据库之前发生并发异常。
-
更新:只有在客户端执行 MarkAsDeleted 时才会出现问题(因此在整个图反序列化后,会导致更改跟踪打开)。如果我在服务器端 MarkAsDeleted 然后坚持回来,即使克隆和 MarkAsDeleted 是在实体上下文之外完成的,行为也符合预期。