节能EF4 POCO的对象发生变化时更新关系 [英] Update relationships when saving changes of EF4 POCO objects

查看:914
本文介绍了节能EF4 POCO的对象发生变化时更新关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

实体框架4,POCO对象和ASP.Net MVC2。我有一个多对多的关系,让博文和标签实体之间说。这意味着,在我的T4生成的POCO类的博文我有:

Entity Framework 4, POCO objects and ASP.Net MVC2. I have a many to many relationship, lets say between BlogPost and Tag entities. This means that in my T4 generated POCO BlogPost class I have:

public virtual ICollection<Tag> Tags {
    // getter and setter with the magic FixupCollection
}
private ICollection<Tag> _tags;

我问一个博文和相关标签从ObjectContext中的一个实例,并将其发送到另一层(在MVC应用程序视图)。后来我回去与改变的属性和关系变化更新的博文。例如它有标签​​AB和C,而新的标签是C和D。在我的特殊例子中有没有新的标签和标签的属性不会改变,所以这应该被保存的唯一的事情就是改变的关系。现在我需要它保存在另一个ObjectContext的。 (更新:现在我想在同一个上下文实例做,也失败了。)

I ask for a BlogPost and the related Tags from an instance of the ObjectContext and send it to another layer (View in the MVC application). Later I get back the updated BlogPost with changed properties and changed relationships. For example it had tags "A" "B" and "C", and the new tags are "C" and "D". In my particular example there are no new Tags and the properties of the Tags never change, so the only thing which should be saved is the changed relationships. Now I need to save this in another ObjectContext. (Update: Now I tried to do in the same context instance and also failed.)

问题:我不能让它正确保存的关系。我什么都试过,我发现:

The problem: I can't make it save the relationships properly. I tried everything I found:


  • Controller.UpdateModel和Controller.TryUpdateModel不起作用。

  • 从上下文然后修改集合不起作用获取旧的博文。 (从下一个点不同的方法)

  • This大概会的工作,但我希望这只是一个解决办法,而不是解决办法:(

  • 试图附加/在每一个可能的组合的博文和/或标签添加/ ChangeObjectState功能。失败。

  • 看起来像我需要什么,但它不工作(我试图修复它,但不能为我的问题)。

  • 试图改变状态/添加/附加/ ...上下文的关系的对象。失败。

  • Controller.UpdateModel and Controller.TryUpdateModel don't work.
  • Getting the old BlogPost from the context then modifying the collection doesn't work. (with different methods from the next point)
  • This probably would work, but I hope this is just a workaround, not the solution :(.
  • Tried Attach/Add/ChangeObjectState functions for BlogPost and/or Tags in every possible combinations. Failed.
  • This looks like what I need, but it doesn't work (I tried to fix it, but can't for my problem).
  • Tried ChangeState/Add/Attach/... the relationship objects of the context. Failed.

直到它不产生错误,至少博文的属性拯救不工作,在我给定的解决方案的工作大多数情况下的手段。有什么关系发生变化:一般标签再次被添加到标签表新的PK和保存的博文引用的,而不是原有的。当然返回的标签具有的PK,和保存/更新方法之前,我检查的PK和它们等于在数据库中的那些,以便可能EF认为它们是新的物体和那些的PK是临时的。

"Doesn't work" means in most cases that I worked on the given "solution" until it produces no errors and saves at least the properties of BlogPost. What happens with the relationships varies: usually Tags are added again to the Tag table with new PKs and the saved BlogPost references those and not the original ones. Of course the returned Tags have PKs, and before the save/update methods I check the PKs and they are equal to the ones in the database so probably EF thinks that they are new objects and those PKs are the temp ones.

我是知道的,而且可能使其无法找到一个自动化的简单的解决方案的问题:当一个POCO对象的集合更改,应由上述虚拟集合属性发生,因为那么FixupCollection伎俩将更新反向引用许多一对多的关系的另一端。然而,当一个视图返回的最新博文对象,这种情况并未发生。这意味着,也许没有简单的解决我的问题,但是这让我很伤心,我会恨EF4-POCO-MVC胜利:(。同时这将意味着,EF不能在MVC环境中做到这一点为准EF4对象类型用于:(。我认为,基于快照的更改跟踪应该找出改变的博文有关系,与现有的PK来标记。

A problem I know about and might make it impossible to find an automated simple solution: When a POCO object's collection is changed, that should happen by the above mentioned virtual collection property, because then the FixupCollection trick will update the reverse references on the other end of the many-to-many relationship. However when a View "returns" an updated BlogPost object, that didn't happen. This means that maybe there is no simple solution to my problem, but that would make me very sad and I would hate the EF4-POCO-MVC triumph :(. Also that would mean that EF can't do this in the MVC environment whichever EF4 object types are used :(. I think the snapshot based change tracking should find out that the changed BlogPost has relationships to Tags with existing PKs.

顺便说一句:我觉得一个一对多的关系,同样的问题发生(谷歌和我的同事说的话)。我就给你在家一试,但即使工作不帮助我在我的应用程序参加六不少一对多的关系:(

Btw: I think the same problem happens with one-to-many relations (google and my colleague say so). I will give it a try at home, but even if that works that doesn't help me in my six many-to-many relationships in my app :(.

推荐答案

让我们尝试这种方式:


  • 附加博文上下文。附加目的是上下文对象的状态之后,所有相关的目的和所有的关系被设定为未改变。

  • 使用context.ObjectStateManager.ChangeObjectState你的博文设置修改

  • 标签通过遍历集合

  • 使用context.ObjectStateManager.ChangeRelationshipState为当前标签和博文的关系设置状态。

  • 的SaveChanges

编辑:

我猜我的评论人给你假的希望,EF会做合并为您服务。我打了很多这样的问题,我的结论说,EF不会为你做这个。我想你也发现我的问题的<一个href=\"http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/65eca787-dced-4040-8836-dd5ee437cfca\">MSDN.在现实中有很多在互联网上这样的问题。的问题是,它没有明确说明如何处理这种情况。所以,让我们对这个问题一起来看看:

I guess one of my comments gave you false hope that EF will do the merge for you. I played a lot with this problem and my conclusion says EF will not do this for you. I think you have also found my question on MSDN. In reality there is plenty of such questions on the Internet. The problem is that it is not clearly stated how to deal with this scenario. So lets have a look on the problem:

问题背景

EF需要使持久性知道哪个记录必须进行更新,插入或删除追踪实体的变化。的问题是,它是ObjectContext的责任来跟踪变化。 ObjectContext的是能够只对附加实体跟踪更改。这是ObjectContext中之外创建的实体不是在所有跟踪。

EF needs to track changes on entities so that persistance knows which records have to be updated, inserted or deleted. The problem is that it is ObjectContext responsibility to track changes. ObjectContext is able to track changes only for attached entities. Entities which are created outside the ObjectContext are not tracked at all.

问题说明

根据以上的介绍我们可以清楚地指出,EF更适合连接的场景中实体始终重视环境 - 典型的WinForm应用程序。 Web应用程序需要断开的场景,之后请求处理和实体内容是到客户端的HTTP响应传递的上下文中被关闭。接下来的HTTP请求提供修改有重新创建实体的内容,连接到新的环境和坚持。康乐通常happends上下文范围(分层架构,具有持久性ignorace)之外。

Based on above description we can clearly state that EF is more suitable for connected scenarios where entity is always attached to context - typical for WinForm application. Web applications requires disconnected scenario where context is closed after request processing and entity content is passed as HTTP response to the client. Next HTTP request provides modified content of the entity which has to be recreated, attached to new context and persisted. Recreation usually happends outside of the context scope (layered architecture with persistance ignorace).

解决方案

那么如何应对这种情况断开?当使用POCO类,我们有3种方式来应对变化的跟踪:

So how to deal with such disconnected scenario? When using POCO classes we have 3 ways to deal with change tracking:


  • 快照 - 需要同样的背景下=没用断开场景

  • 动态跟踪代理 - 需要同样的背景下=没用断开场景

  • 手动同步。

在单一实体手动同步是一件容易的事。你只需要附加的实体,并呼吁ADDOBJECT插入,DeleteObject的在ObjectStateManager删除或设置状态修改为可更新。真正的痛苦来当你要处理的对象图,而不是单一的实体。当你要处理的独立协会(那些不使用外键属性)和多对多关系,这种疼痛更是雪上加霜。在这种情况下,你必须手动同步对象图中每个实体而且在对象图中每个关系。

Manual synchronization on single entity is easy task. You just need to attach entity and call AddObject for inserting, DeleteObject for deleting or set state in ObjectStateManager to Modified for updating. The real pain comes when you have to deal with object graph instead of single entity. This pain is even worse when you have to deal with independent associations (those that don't use Foreign Key property) and many to many relations. In that case you have to manually synchronize each entity in object graph but also each relation in object graph.

手动同步,提出解决方案,如通过MSDN文档:安装和卸下对象说:

Manual synchronization is proposed as solution by MSDN documentation: Attaching and Detaching objects says:

的对象被附连到对象
  上下文不变的状态。如果你
  需要改变的对象的状态
  或的关系,因为你知道
  你的对象是在修改
  脱管状态,使用其中一个
  下面的方法。

Objects are attached to the object context in an Unchanged state. If you need to change the state of an object or the relationship because you know that your object was modified in detached state, use one of the following methods.

提到的方法是ChangeObjectState和ObjectStateManager =手动更改跟踪的ChangeRelationshipState。类似的建议是在其他MSDN文档的文章:定义和管理关系说:

Mentioned methods are ChangeObjectState and ChangeRelationshipState of ObjectStateManager = manual change tracking. Similar proposal is in other MSDN documentation article: Defining and Managing Relationships says:

如果您正在使用断开工作
  对象,则必须手动管理
  同步。

If you are working with disconnected objects you must manually manage the synchronization.

此外还有<一个href=\"http://weblogs.asp.net/aaguiar/archive/2007/03/30/ado-net-orcas-entity-framework-and-disconnected-operation.aspx\">blog帖子与EF V1其中批评EF的正是这种行为。

Moreover there is blog post related to EF v1 which criticise exactly this behavior of EF.

原因解决方案

EF有许多有用的操作和如刷新,的Load ,的 ApplyCurrentValues​​ ApplyOriginalValues​​ ,的MergeOption 等,但通过我的调查所有这些功能仅针对单一实体,并且只影响标量preperties (=没有导航属性和关系)。我宁愿不测试这个方法与嵌套在实体复杂类型。

EF has many "helpful" operations and settings like Refresh, Load, ApplyCurrentValues, ApplyOriginalValues, MergeOption etc. But by my investigation all these features work only for single entity and affects only scalar preperties (= not navigation properties and relations). I rather not test this methods with complex types nested in entity.

其他建议的解决方案

而不是真正的合并功能EF团队提供一些所谓的自我跟踪实体(STE)的不解决问题。只有当相同的实例被用于整个处理首先STE作品。在Web应用程序,除非你存储实例视图状态或会话情况并非如此。由于我是使用EF很不爽,我去检查的NHibernate的功能。首先观察说,NHibernate的或许有这样的functionality.

Instead of real Merge functionality EF team provides something called Self Tracking Entities (STE) which don't solve the problem. First of all STE works only if same instance is used for whole processing. In web application it is not the case unless you store instance in view state or session. Due to that I'm very unhappy from using EF and I'm going to check features of NHibernate. First observation says that NHibernate perhaps has such functionality.

结论

我将结束与单个链接到另一个<一本的假设href=\"http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/fdc5c7ac-dcf8-45a8-ab11-2ffbc338b0e5\">related在MSDN论坛问题。检查Zeeshan Hirani的回答。他是实体框架4.0 食谱的作者。如果他说的对象图的自动合并,不支持,我相信他。

I will end up this assumptions with single link to another related question on MSDN forum. Check Zeeshan Hirani's answer. He is author of Entity Framework 4.0 Recipes. If he says that automatic merge of object graphs is not supported, I believe him.

但仍然有可能,我是完全错误的,一些自动合并功能的EF存在。

But still there is possibility that I'm completely wrong and some automatic merge functionality exists in EF.

编辑2:

正如你可以看到这个已经加入到<一个href=\"https://connect.microsoft.com/VisualStudio/feedback/details/307588/disconnected-change-tracking-for-linq-to-sql-and-entity-framework\">MS连接的建议,在2007年MS已经关闭了其作为在下一版本中做了一些事情,但实际上什么也没做,以提高除STE这一空白。

As you can see this was already added to MS Connect as suggestion in 2007. MS has closed it as something to be done in next version but actually nothing had been done to improve this gap except STE.

这篇关于节能EF4 POCO的对象发生变化时更新关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆