【问题标题】:Azure App Service - Offline Sync - PullAsync TransactionAzure 应用服务 - 离线同步 - PullAsync 事务
【发布时间】:2017-06-29 12:41:48
【问题描述】:

我正在开发一个使用 Xamarin.Forms 和 Azure App Service 的应用程序。 用户必须明确执行数据同步。当用户开始数据同步时,会执行很多这样的方法来从服务器获取当前数据:

 await this.ISyncTable.PullAsync(queryId, query, cancellationToken).ConfigureAwait(false);

我的问题:应用程序可能会进入不一致的状态。例如,当用户在数据同步完成之前关闭应用程序时。在这种状态下,应用程序不可用。

编辑:

为了更容易理解:假设我有一个表“ToDoItem”和“ToDoCategory”。用户开始数据同步。数据同步运行,所有 ToDoItem 均已成功检索。在下一步中,数据同步将获取 ToDoCategories(对 PullAsync 的另一个调用),但在此之前用户关闭应用程序。现在我有所有 ToDoItems 但没有 ToDoCategories。但是,如果没有 ToDoCategories,该应用程序将无法使用。这是一个非常简单的例子。实际项目中的数据结构要复杂得多。实体之间有很多依赖关系。

记录同步错误/取消并在下一次应用启动时提示用户再次同步是没有解决方案的。假设在下一次应用启动时,用户没有互联网连接并且无法执行数据同步。在下一次成功的数据同步之前,我无法锁定应用程序。

有没有办法在一个事务中运行多个 PullAsync 操作?

【问题讨论】:

    标签: android ios azure xamarin azure-mobile-services


    【解决方案1】:

    有没有办法在一个事务中运行多个 PullAsync 操作?

    简短的回答是不,没有。在所有 PullAsync 操作完成时设置一个标志,或跟踪哪些表已成功同步。

    记录同步错误/取消并在下次应用启动时提示用户进行另一次同步是没有解决方案的。假设在下一次应用启动时,用户没有互联网连接并且无法执行数据同步。在下一次成功的数据同步之前,我无法锁定应用程序。

    如果用户开始同步但在同步完成之前离开应用程序,那么您的应用程序在第二次运行时的预期行为是什么?完成同步?提示用户重新开始?

    另外考虑应用可能会在用户离开后继续在后台同步。在 iOS 中,您必须使用 UIApplication beginBackgroundTaskWithExpirationHandler 与操作系统协调。

    【讨论】:

    • 感谢您的回答。我认为微软应该直接在他们的 SDK 中拥有这样的功能。它不仅仅是用户关闭应用程序。同步期间可能存在网络错误。主要问题是同步中止时本地设备上的数据可能不一致。在不完整同步期间,需要类似回滚的功能来撤消本地数据库中的所有更改。我会考虑并在这里发布我的解决方案...
    • 我同意,SDK 并不适合具有多个相互依赖的表的应用程序。您可能希望创建一个自定义 API,在一个 HTTP 请求中返回整个数据集合并将结果存储在本地,但是您没有利用 SDK 的离线同步功能。
    • 另请参阅 Adrian Hall 关于使用 Azure 移动应用构建移动应用的书,特别是关于对象关系的这一部分:adrianhall.github.io/develop-mobile-apps-with-csharp-and-azure/…“我们没有允许在数据库中更新多个表的事务同时。每个表中的每条记录都是单独更新的。离线同步使用的推送过程对表之间的关系如何工作产生重大影响。具体而言,只有单向关系将在离线同步世界中工作。"
    【解决方案2】:

    我的问题:应用程序可能会进入不一致的状态。例如,当用户在数据同步完成之前关闭应用程序时。在这种状态下,应用程序不可用。

    如果您指定查询 id(非空),那么您将使用 增量同步 进行拉取操作。正如官方document 提到的增量同步:

    拉取操作的第一个参数是一个仅在客户端使用的查询名称。如果使用非空查询名称,Azure 移动 SDK 会执行增量同步。 每次拉取操作返回一组结果时,该结果集中的最新 updatedAt 时间戳都会存储在 SDK 本地系统表中。随后的拉取操作仅检索该时间戳之后的记录

    成功检索数据并更新到本地数据存储后,客户端 SDK 将使用提取结果中的最新 updatedAt 时间戳更新/插入 __config 表,以及 SQLite 数据库的 ID 等于 deltaToken|{table-name}|{query-id}如下:

    另外,在获取记录后,客户端 SDK 会执行以下 sql 语句来更新您的本地数据存储:

    假设您已检索到 TodoItem 表的 50 条记录。

    开始交易

    插入或忽略 [TodoItem] ([id]) 值 (@p0),(@p1),(@p2),(@p3),(@p4),(@p5),(@p6) ,(@p7),(@p8),(@p9),(@p10),(@p11),(@p12),(@p13),(@p14),(@p15),(@p16) ,(@p17),(@p18),(@p19),(@p20),(@p21),(@p22),(@p23),(@p24),(@p25),(@p26) ,(@p27),(@p28),(@p29),(@p30),(@p31),(@p32),(@p33),(@p34),(@p35),(@p36) ,(@p37),(@p38),(@p39),(@p40),(@p41),(@p42),(@p43),(@p44),(@p45),(@p46) ,(@p47),(@p48),(@p49)

    UPDATE [TodoItem] SET [Text] = @p0,[UserId] = @p1 WHERE [id] = @p2

    UPDATE [TodoItem] SET [Text] = @p0,[UserId] = @p1 WHERE [id] = @p2

    .

    .

    提交交易

    开始交易

    插入或忽略 [__config] ([id]) 值 (@p0)

    UPDATE [__config] SET [value] = @p0 WHERE [id] = @p1

    提交交易

    MaxPageSize 的默认MaxPageSize 是 50,如果三个有更多数据,客户端会自动发送多个请求。注意在页面中检索记录后,检索到的数据将更新到您的本地数据存储中,然后将发送下一页请求。据我了解,如果用户在数据同步完成之前关闭应用程序,数据不会更新到最新的,当用户再次打开应用程序时,丢失的数据将根据最新更新到您的数据存储中updatedAt 时间戳。

    【讨论】:

    • 感谢您的回答,但我认为这不是与我的问题相关的解决方案。为了更容易理解:假设我有一个表“ToDoItem”和“ToDoCategory”。用户开始数据同步。数据同步运行,所有 ToDoItem 均已成功检索。在下一步中,数据同步将获取 ToDoCategories(对 PullAsync 的另一个调用),但在此之前用户关闭应用程序。现在我有所有 ToDoItems 但没有 ToDoCategories。但是,如果没有 ToDoCategories,该应用程序将无法使用。我更新了我的第一篇文章。
    猜你喜欢
    • 2015-11-25
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多