自我跟踪实体(STE)和EF4和mVC2的部分更新

时间:2010-01-22 15:39:01

标签: .net entity-framework self-tracking-entities

我有一个MVC2应用程序,我开始使用STE。我正在寻找有关更新如何运作的一些说明。

背景

如果我有一个包含相关类别实体和相关帖子/评论实体的博客实体。在MVC中,我正在使用主要的Blog实体和类别而不是相关的帖子呈现视图。当我将Blog实体回发到服务器时,我可以看到相关类别,但不能查看被序列化回服务器的实体中的帖子(因为它们不在视图中)。此外,Blog实体的更改状态为“已添加”。

然后我尝试在此Blog实体上调用Applychanges()SaveChanges()来执行更新,但由于与帖子的FK关系以及数据库中存在相关帖子这一事实,它失败了没有附加到我发回的实体。

进行一些进一步的测试...如果我在连接到服务器时获取了Blog实体的当前实例(包含所有相关的FK实体)(状态=未更改),请修改属性(state = Modified)并更新它按预期工作。

所以我的问题: 如果我有相关的实体未在视图中呈现,因此如果更新有效,则不会使用Blog实体回发?

为什么Blog实体会以“已添加”状态回复而不是“已修改”?我会假设它将为所有已更改的实体返回一个“已修改”的更改状态,然后当我调用ApplyChanges/SaveChanges()时,只有修改后的项目会尝试更新,这就是为什么我不需要所有相关实体。

我是否能够直接从客户端和ApplyChanges()/SaveChanges()传递实体,或者我应该将实体发回服务器,从数据库中获取现有副本,对该副本应用更改然后发布现有的物体回来了?

4 个答案:

答案 0 :(得分:1)

关于你的第一个问题:

  

然后我尝试调用Applychanges()和   SaveChanges()在此Blog实体上   执行更新,但失败了   因为与FK的关系   帖子和有的事实   数据库中的相关帖子但没有   附加到我发送的实体   回来。

这可能是由您的第二个问题(“已添加”状态而非“已修改”)引起的。 Context可能正在尝试添加Blog而不是尝试保存更改,因此会出现FK约束错误。

至于你的第二个问题:

  

为什么Blog实体会回复   具有“已添加”状态而不是   '改性'?我会认为它会   用'修改'回来   所有已更改实体的已更改状态   然后我打电话的时候   ApplyChanges / SaveChanges()只有   修改过的项目会尝试更新   这就是为什么我不需要所有人   相关实体。

要考虑的问题是“您是否在服务器和客户端上使用相同类型生成的代码”?当您使用数据服务元数据生成类型时,STE已known to not keep track of changes。对于STE,有一段重要的代码在构造函数中被激活,而这些代码不会通过元数据生成的类型持续存在,因此是导致此问题的原因。

至于你的最后一个问题:

  

我应该能够通过实体吗?   直接来自客户和   ApplyChanges()/ SaveChanges()或应该   我要回邮件到服务器了   实体,从中获取现有副本   数据库,对其应用更改   复制然后发布现有的   反对?

是的,可以(我已经测试过)将ApplyChanges()/ SaveChanges()传递给直接来自客户端的实体,无论实体最初来自哪里(来自要在客户端上修改或创建的服务器)作为要添加的新实体。)

答案 1 :(得分:1)

我对此的观察是,虽然EF4中的STE在客户端处于有状态的情况下运行良好,但在无状态环境中它们无法正常工作。

MVC突出了这个缺点。例如,让我们看一个典型的实体“User”和一个典型的场景,EditController和Edit视图。

当我们进入我们的数据库(获取用户,开始跟踪,返回)或我们的服务(更改跟踪在反序列化后自动打开)时,实体在控制器和视图中按预期运行。

然而,当Post回来时,我们的Controller方法得到的实体是一个新实体,而不是Get请求给我们的实体。所以这个实体没有变化跟踪,处于已添加状态,如果我们将它视为在Get阶段交给我们的同一个实例,它将会破坏我们的数据库。

目前,您可以将EF4 STE标记为已修改,应用更改并在实体为新实体时保存或仅将其标记为已添加。这就是你现在可以做的所有事情来支持这种情况。除非MVC团队提出更好的模式来支持STE,或者除非在实例化模型以缓存实体实例时更改模型绑定器的默认行为...

答案 2 :(得分:0)

我们在非常类似的问题上挣扎 - 围绕更新。根据那里的信息,我们收集到STE尚未准备好生产,但确实考虑使用它们。

无论如何,这里的问题围绕着附加和分离之间的区别,以及ObjectStateManager和STE之间的相互作用..在你描述的那个确实有效的例子中,它起作用,因为它附着了整个时间,而STE从不实际上转换为使用其STE行为(这仅在被反序列化到客户端之后发生,或者它们被重新附加到附加实体)。

回答他们出现的原因:

  

例如,当实例化STE时,停用更改跟踪并更改更改跟踪器中的默认状态。

我发现这一切都令人困惑,对Julia Lerman的采访和在线发帖似乎表明目前的STE发布还没有为现实世界做好准备......

请参阅Diego Vega(EF小组)的回复

  

在此模式下使用STE时,它们的行为与普通的POCO对象大致相同。例如,您可以直接操作图形或使用ObjectContext和ObjectStateManager中的API,并且必须调用DetectChanges以确保状态管理器在调用SaveChanges之前随时与图形同步。

     

最重要的是,标准的Object Services API不知道STE,因此,诸如AcceptAllChanges之类的方法(在您的示例中,在SaveChanges中隐式调用它并将投诉对象的ObjectStateManager状态重置为Unchanged)绝对没有影响STEs存储的状态。

http://social.msdn.microsoft.com/Forums/en/adonetefx/thread/557e6db0-51df-45e5-a2e9-c31995969554

希望这有帮助

答案 3 :(得分:0)

我不相信我曾经说过STE没有为现实世界做好准备。他们不会适合所有人。对于只想要能够轻松工作的数据集/数据表用户来说,它们是一个非常好的工具。对于这些用户(并且有很多用户)将STE实体放在客户端应用程序中并不是一件坏事。可能已经拥有管道的两侧。