【问题标题】:Core Data Sync - Tracking Deleted Objects核心数据同步 - 跟踪删除的对象
【发布时间】:2012-02-19 10:27:12
【问题描述】:

我正在为我正在开发的 iPad 应用程序设置基本同步服务。目标是在 iPad 应用程序的多个实例中保持数据一致,并在网络上拥有数据的只读版本,从而推出自定义解决方案。

目前的流程是这样的:

  • 每个实体都有一个“created”、“modified”和“UUID”字段,这些字段由 Core Data 自动更新
  • 在同步时,在最后一个同步日期之后创建或修改日期的每个实体都被序列化为 JSON 并发送到服务器
  • 服务器使用客户端生成的 UUID 作为 PK 将任何更改持久保存到 MySQL 数据库(如果存在冲突,它只使用最近修改的实体作为“真实”版本,没有什么特别的)并发回任何更新的实体给客户
  • 然后客户端将这些更改合并回其核心数据数据库

这一切似乎都运行良好。我的问题是如何使用此方法跟踪已删除的对象?我猜我可以为每个实体添加一个“已删除”标志,并在客户端删除某些内容时设置它,然后我可以将该更改与其余同步数据一起推送到服务器。同步完成后,客户端实际上可以删除这些实体。我的问题是:

  • 我可以覆盖 Core Data 的删除方法来自动设置这个标志吗?
  • 这是否需要将所有已删除的实体无限期地保留在服务器上?我们无法知道每个客户端何时同步并实际删除了每个实体(我目前没有跟踪客户端实例)
  • 有更好的方法吗?

【问题讨论】:

    标签: iphone mysql ios ipad core-data


    【解决方案1】:

    您如何保留一个带有 UUID 和创建/更新/删除字段的增量历史表,也许每次更新都有一个修订号?因此,您会保留一份自上次成功同步以来所做更改的小清单。

    这样,如果您删除一个对象,您可以在增量历史表中添加一个带有已删除 UUID 的条目并将其标记为已删除。与创建和更新的对象一样,您只需要检查增量表即可查看服务器需要删除、更新、创建哪些项目等。您甚至可以将每个修订存储在服务器上以支持回滚到以前的版本未来,如果你愿意的话。

    我认为修订号比依赖可能手动更改的客户时钟更好。

    您可以在每个保存过程之前使用 NSManagedObjectContext 的 insertObjects、updatedObjects、deletedObjects 方法来创建增量对象 :)

    我的 2 美分

    【讨论】:

    • 非常感谢。我现在采用了一种混合方法,正如我在问题中描述的那样进行同步,但现在也维护一个已删除对象的表。将来我会考虑迁移到完全 delta 的系统。
    【解决方案2】:

    关于你的第二个问题:如果你愿意,你可以设计这个,这样服务器就不必保留已删除的记录。让每个应用程序知道给定的数据(基于其 UUID)是否存储在服务器上(例如,添加 existsOnServer 属性或类似属性)。当在应用程序中创建新项目时,这开始为 false,但在第一次同步到服务器后设置为 true。这样,如果应用程序稍后尝试同步,但找不到 UUID,则可以区分两种情况:如果 existsOnServer 为 false,则此项目是新创建的,应该同步到服务器,但如果为 true那么可以认为之前已经在服务器上,但是现在已经被删除了,所以你也可以在应用中删除它。

    我可能会反对这种方法,因为它对我来说似乎更容易出错(我认为数据库或连接错误被错误地解释为删除)并且在您的服务器上保留记录通常不会有什么大不了的,但这是可能的。 dzeikei 建议的“delta-approach”可以同时使用,因此对服务器上不存在的记录的更新表示它已被删除,而插入则不会。

    【讨论】:

      【解决方案3】:

      您是否必须在服务器上保留已删除的对象完全取决于您的需要。您将需要在本地设置一个已删除标志来标记为已删除以进行同步,也可能在服务器上根据您的回滚愿望。

      我之前已经通过几种方式解决了这个问题。这是一种可能性:

      当客户端删除某些内容时,只需将其标记为在本地删除并在同步期间从服务器中删除(此时您可以从核心数据中清除)。当其他客户端请求访问该数据时,请发回 HTTP 404,因为您不再拥有该对象。此时,客户端可以在本地删除实体。现在,如果客户端请求一个事物列表并且该对象已被删除,那么它将从他返回的事物列表中丢失,因此您可以检测到并删除它。我在客户端执行此操作,方法是在收到来自服务器的响应时创建对象 ID 数组并删除任何没有这些 ID 的本地对象。

      我们在服务器上有一个已删除的字段,但只是为了能够在某些内容被意外删除时回滚。

      当然,您可以将已删除的对象返回给客户端,以便他们知道要删除,但是如果您不想在服务器上保留副本,则必须做出一些假设,即客户端会在一段时间内全部更新.然后您可以在该时间范围到期后进行垃圾收集。

      虽然我不太喜欢这种解决方案。如果您的数据太大而无法要求所有对象进行完全同步,您可以使用当前的合并策略来创建和更新,然后运行单独的调用来检查已删除的项目。该调用可以简单地询问客户端应该在设备上具有的所有 ID。它可以删除那些不存在的。或者它可以发送客户端上的所有 ID 并返回要删除的 ID 列表。

      我认为,如果您想要更自以为是的建议,您必须提供有关数据性质的更多详细信息。

      【讨论】:

        【解决方案4】:

        如果你还没有,你可以看看Cross-Platform Data Synchronization by Dan Grover。这是一篇关于同步和 iOS 的写得很好的论文。

        关于你的问题:

        1. 您可以避免在 Core Data 中删除文件并设置“已删除标志”:只需更新文件而不是删除它。您可以创建自己的“删除”方法,该方法实际上会调用和更新记录上的标志。

        2. 始终为服务器和每个客户端上的每条记录保留一个 last_sync 和一个 last_updated。这样一来,您就可以始终知道某人何时在任何地方更改了某些内容,以及该更改是否与“真实数据库”同步。

        3. 跟踪已删除的文件是一件很难的事情,我想最好的方法是跟踪每个表的同步历史记录,但这是一项艰巨的任务。使用这种“真实数据库”配置的最简单方法是标记文件,这样是的,您应该将数据保存在服务器和客户端上。

        【讨论】:

          【解决方案5】:

          在两个表之间同步数据的过程中,当表行相同时,一些记录或被删除。并且当行不同时正确同步,我使用此代码单击图像上的此处

          【讨论】:

          • 嗨,Gulshekhan,请不要包含代码图像,而是包含代码。
          猜你喜欢
          • 1970-01-01
          • 2012-06-17
          • 1970-01-01
          • 2016-10-27
          • 2016-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多