简体   繁体   English

在实体框架中使用更改跟踪撤消/重做

[英]Undo / Redo with change tracking in Entity Framework

I'm trying to implement an Undo / Redo feature based on entity framework with POCO entities. 我正在尝试基于具有POCO实体的实体框架实现撤消/重做功能。 Therefor after each change that I want to track I call the ChangeTracker for any modification to entities an I call the ObjectStateManger for changes to relationships (ie navigation properties). 因此,在我要跟踪的每次更改之后,我将ChangeTracker称为对实体的任何修改,而我将ObjectStateManger称为对关系的更改(即导航属性)。 I store all the changes with the current and previous values to be able to go back and forth in the history. 我将所有更改与当前值和先前值一起存储,以便能够在历史记录中来回移动。

My problem now is that for entities with a navigation property and a corresponding foreign key these two values are not properly synced if the referenced entity was newly added to the DbContext. 我现在的问题是,对于具有导航属性和相应外键的实体,如果将引用的实体新添加到DbContext,则这两个值将无法正确同步。

To clarify: Say I have these classes: 澄清一下:说我有这些课程:

public class EntityFilter
{
    [Key]
    public Guid ID { get; set; }

    public virtual ICollection<EntityConnection> IsSource { get; set; }

    public virtual ICollection<EntityConnection> IsSink { get; set; }

    //other stuff
}

public class EntityConnection
{
    [Key]
    public Guid SinkFilterID { get; set; }

    [ForeignKey("SinkFilterID")]
    public virtual EntityFilter Sink { get; set; }

    public Guid SourceFilterID { get; set; }

    [ForeignKey("SourceFilterID")]
    public virtual EntityFilter Source { get; set; }

    //more stuff
}

EntityConnection is basically a many-to-many relationship between filters, but it actually contains more fields which is why I cannot get rid of it. EntityConnection基本上是过滤器之间的多对多关系,但实际上它包含更多字段,这就是为什么我不能摆脱它。 Also I want to be as general as possible and not depend on our actual data model. 我也想尽可能地笼统,而不依赖于我们的实际数据模型。

The problem arises if I add a new filter and then connect it to an existing filter (could also be a new one). 如果添加新的过滤器,然后将其连接到现有过滤器(也可能是新过滤器),则会出现问题。 Undoing the connection is still ok, but when I try to redo my program will crash. 取消连接仍然可以,但是当我尝试重做时,我的程序将崩溃。 I can see in the restored connection that the foreign key SinkFilterID has the correct value but Sink is null (the same might happen for source, depending on the direction of the connection). 我可以在还原的连接中看到,外键SinkFilterID具有正确的值,但Sinknull (对于源,可能会发生同样的情况,具体取决于连接的方向)。 Manually calling DetectChanges makes no difference. 手动调用DetectChanges没什么区别。 Adding a connection between two existing filters (ie they are already stored in the db before) is no problem. 在两个现有的过滤器之间添加连接(即它们已经存储在数据库中)没有问题。

The detected changes for a new connection of this type only contain entity changes from the ChangeTracker and no relationship changes from the ObjectStateManger . 对于此类型的新连接,检测到的更改仅包含ChangeTracker实体更改,而ObjectStateManger没有关系更改。 I guess this is because the relationship is already handled by the foreign key, which is included in the properties from PreviousValues . 我猜这是因为该关系已经由外键处理,该外键包含在PreviousValues的属性中。

I've read that entities in the EntityState.Added state get temporary keys and that change tracking for them is not fully supported. 我读过EntityState.Added状态中的实体获取临时键,并且不完全支持对它们的更改跟踪。 Can I get this to work somehow? 我能以某种方式使它工作吗?

I've tried to check with the MetadataWorkspace if my updated entities have a foreign key and a corresponding navigation property and in that case update it manually via reflection, but I'm not sure what data I actually have to check. 我尝试与MetadataWorkspace进行检查,如果我更新的实体具有外键和相应的导航属性,并且在这种情况下,可以通过反射手动进行更新,但是我不确定实际上必须检查哪些数据。

Is there a way to keep foreign keys and navigation properties to added entities in sync? 有没有办法使外键和导航属性与添加的实体保持同步? Or do you have any suggestions what I might try? 还是您有什么建议我可以尝试?

Thank you very much. 非常感谢你。

Here is what I ended up with: 我最终得到的是:

I keep a separate list of all the added entities. 我保留了所有添加实体的单独列表。 Then when I have to restore a navigation property that is backed by a foreign key I search that list and manually set the navigation property. 然后,当我必须还原由外键支持的导航属性时,我会搜索该列表并手动设置导航属性。 The hardest part was to figure out how to check in the data model if this fixup was at all needed and to find the name of the corresponding property. 最困难的部分是弄清楚如何在数据模型中检入是否完全需要此修补程序,以及如何找到相应属性的名称。

The overall system still has some flaws for maximum generality but it works quite well for what we need. 整个系统仍存在一些缺陷,无法实现最大的通用性,但对于我们需要的功能来说效果很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM