代码之家  ›  专栏  ›  技术社区  ›  Jay

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

  •  3
  • Jay  · 技术社区  · 15 年前

    我有一个MVC2应用程序,在那里我开始使用 STE 我在找一些关于更新应该如何工作的说明。

    背景:

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

    然后我试着打电话 Applychanges() SaveChanges() 在这个博客实体上执行一个更新,它失败了,因为fk与文章的关系,以及数据库中有相关的文章,但没有附加到我发送回的实体上。

    通过一些进一步的测试…如果我在连接到服务器(state=unchanged)时抓取blog实体的当前实例(以及所有相关的fk实体),修改一个属性(state=modified)并按预期更新它。

    所以我的问题是: 如果我有相关的实体没有在视图中呈现,因此没有用博客实体回发,那么更新是否有效?

    为什么博客实体会以“已添加”状态而不是“已修改”状态返回日志?我假设它会为所有更改的实体返回一个“modified”changedstate,然后当我调用 ApplyChanges/SaveChanges() 只有修改过的项才会尝试更新,这就是我不需要所有相关实体的原因。

    我是否可以直接从客户那里传递实体,以及 ApplyChanges()/SaveChanges() 还是应该将实体发回服务器,从数据库中获取现有副本,对该副本应用更改,然后将现有对象发回?

    4 回复  |  直到 15 年前
        1
  •  1
  •   Tri Q Tran    15 年前

    关于你的第一个问题:

    然后我尝试调用applychanges()和 将此日志实体上的changes()保存到 执行更新,但失败 因为FK与 帖子和事实上 数据库中的相关文章,但不是 附属于我发送的实体 后退。

    这可能是由于您的第二个问题(“添加”状态而不是“修改”)。上下文可能试图添加博客而不是保存更改,因此会出现FK约束错误。

    关于第二个问题:

    博客实体为什么要发回帖子 状态为“已添加”,而不是 “修改”?我想会的 带着“修改”回来 所有已更改实体的ChangedState 当我打电话的时候 applychanges/savechanges()仅 修改的项目将尝试更新 这就是为什么我不需要所有 相关实体。

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

    至于你最后的问题:

    我能通过一个实体吗 直接来自客户和 applychanges()/savechanges()或应 我要回服务器 实体,从中获取现有副本 数据库,对其应用更改 复制并发布现有 返回对象?

    是的,可以(我已经对此进行了测试)将changes()/savechanges()应用于直接来自客户机的实体,而不管实体最初来自何处(来自要在客户机上修改或创建为要添加的新实体的服务器)。

        2
  •  1
  •   Will    15 年前

    我对此的观察是,虽然ste在ef4中在客户机有状态的情况下工作得很好,但是在无状态环境中它们并不像预期的那样工作。

    MVC强调了这一缺点。例如,让我们以一个典型的实体“用户”和一个典型的场景、editcontroller和edit视图为例。

    当我们转到数据库(get user、start tracking、return)或服务(在反序列化后更改跟踪自动打开)时,实体在控制器和视图中的行为与预期一致。

    但是,当post返回时,我们的controller方法得到的实体是 新实体 而不是在GET请求时提供给我们的。因此,这个实体没有变更跟踪,处于添加状态,如果我们将它作为在get阶段传递给我们的相同实例来处理,它将炸毁我们的数据库。

    当前,您可以将EF4STE标记为已修改、应用更改并在实体真正是新的或只是错误地标记为已添加时保存。这就是您现在所能做的一切来支持这个场景。除非MVC团队想出更好的模式来支持STES,或者除非在实例化模型以缓存实体实例时更改模型绑定器的默认行为…

        3
  •  0
  •   Bobby    15 年前

    我们在非常相似的问题上挣扎——周围的更新。根据那里的信息,我们收集到STE还没有准备好生产,但确实考虑使用它们。

    无论如何,这里的问题集中在附加和分离之间的区别,以及ObjectStateManager和STES之间的交互。在您描述的例子中,这确实有效,因为它一直连接在一起,并且ste从未真正转换到使用其ste行为(这只在反序列化到客户机之后发生,或者它们重新连接到一个附加的实体)。

    为了回答它们为什么会以添加的形式出现:

    例如,当stes被实例化时,变更跟踪将被停用,并添加变更跟踪程序中的默认状态。

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

    请看迭戈·维加(EF团队)的回复。

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

    最重要的是,标准对象服务API不知道STES,因此,诸如AcceptAllChanges(即在保存更改期间隐式调用并将投诉对象的ObjectStateManager状态重置为Unchanged的方法)等方法对STES存储的状态绝对没有影响。

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

    希望这有帮助

        4
  •  0
  •   Julie Lerman    15 年前

    我不相信我曾经说过马还没有准备好面对现实世界。他们只是不适合每个人。对于数据集/数据表用户来说,它们是一个非常好的工具,他们只需要一些可以轻松工作的东西。对于这些用户(他们中有很多人)来说,将ste实体放在客户机应用程序中并不是一件坏事。他们可能已经拥有管道的两侧。