为 Xamarin.Forms 移动应用启用脱机同步Enable offline sync for your Xamarin.Forms mobile app


本教程介绍适用于 Xamarin.Forms 的 Azure 移动应用的脱机同步功能。This tutorial introduces the offline sync feature of Azure Mobile Apps for Xamarin.Forms. 脱机同步允许最终用户与移动应用交互(查看、添加或修改数据),即使在没有网络连接时也是如此。Offline sync allows end users to interact with a mobile app--viewing, adding, or modifying data--even when there is no network connection. 在本地数据库中存储更改。Changes are stored in a local database. 设备重新联机后,这些更改会与远程服务同步。Once the device is back online, these changes are synced with the remote service.

本教程基于在完成[创建 Xamarin iOS 应用]教程时创建的移动应用的 Xamarin.Forms 快速入门解决方案。This tutorial is based on the Xamarin.Forms quickstart solution for Mobile Apps that you create when you complete the tutorial [Create a Xamarin iOS app]. Xamarin.Forms 的快速入门解决方案包含用于支持脱机同步的代码,只需启用即可使用。The quickstart solution for Xamarin.Forms contains the code to support offline sync, which just needs to be enabled. 本教程会更新快速入门解决方案,以打开 Azure 移动应用的脱机功能。In this tutorial, you update the quickstart solution to turn on the offline features of Azure Mobile Apps. 我们还重点介绍了该应用中的特定于脱机的代码。We also highlight the offline-specific code in the app. 如果不使用下载的快速入门解决方案,必须将数据访问扩展包添加到项目。If you do not use the downloaded quickstart solution, you must add the data access extension packages to your project. 有关服务器扩展包的详细信息,请参阅使用适用于 Azure 移动应用的 .NET 后端服务器 SDKFor more information about server extension packages, see Work with the .NET backend server SDK for Azure Mobile Apps.

若要了解有关脱机同步功能的详细信息,请参阅 Azure 移动应用中的脱机数据同步 主题。To learn more about the offline sync feature, see the topic Offline Data Sync in Azure Mobile Apps.

启用快速入门解决方案中的脱机同步功能Enable offline sync functionality in the quickstart solution

通过使用 C# 预处理器指令将脱机同步代码包含在项目中。The offline sync code is included in the project by using C# preprocessor directives. 定义 OFFLINE_SYNC_ENABLED 符号时,这些代码路径包含在生成中。When the OFFLINE_SYNC_ENABLED symbol is defined, these code paths are included in the build. 对于 Windows 应用,还必须安装 SQLite 平台。For Windows apps, you must also install the SQLite platform.

  1. 在 Visual Studio 中,右键单击解决方案,再单击“管理解决方案的 NuGet 包…” ,然后在解决方案的所有项目中搜索并安装 Microsoft.Azure.Mobile.Client.SQLiteStore NuGet 包。In Visual Studio, right-click the solution > Manage NuGet Packages for Solution..., then search for and install the Microsoft.Azure.Mobile.Client.SQLiteStore NuGet package for all projects in the solution.

  2. 在解决方案资源管理器中,从名称中包含 Portable 的项目(该项目是可移植类库项目)中打开 TodoItemManager.cs 文件,然后取消注释以下预处理器指令:In the Solution Explorer, open the TodoItemManager.cs file from the project with Portable in the name, which is Portable Class Library project, then uncomment the following preprocessor directive:

  3. (可选)若要支持 Windows 设备,请安装以下 SQLite 运行时包之一:(Optional) To support Windows devices, install one of the following SQLite runtime packages:

  4. (可选)在每个 Windows 应用项目中,右键单击“引用” 再单击“添加引用...” > ,展开“Windows” 文件夹 >“扩展” 。(Optional) In each Windows app project, right-click References > Add Reference..., expand the Windows folder > Extensions. 启用合适的 SQLite for Windows SDK 以及 Visual C++ 2013 Runtime for Windows SDK。Enable the appropriate SQLite for Windows SDK along with the Visual C++ 2013 Runtime for Windows SDK. 每个 Windows 平台的 SQLite SDK 名称略有不同。The SQLite SDK names vary slightly with each Windows platform.

查看客户端同步代码Review the client sync code

下面简要概述了在教程代码的 #if OFFLINE_SYNC_ENABLED 指令中已包含的内容。Here is a brief overview of what is already included in the tutorial code inside the #if OFFLINE_SYNC_ENABLED directives. 脱机同步功能在可移植类库项目的 TodoItemManager.cs 项目文件中。The offline sync functionality is in the TodoItemManager.cs project file in the Portable Class Library project. 有关功能的概念性概述,请参阅 Azure 移动应用中的脱机数据同步For a conceptual overview of the feature, see Offline Data Sync in Azure Mobile Apps.

  • 表操作之前,必须初始化本地存储区。Before any table operations can be performed, the local store must be initialized. 使用以下代码在 TodoItemManager 类构造函数中初始化本地存储数据库:The local store database is initialized in the TodoItemManager class constructor by using the following code:

      var store = new MobileServiceSQLiteStore(OfflineDbPath);
      //Initializes the SyncContext using the default IMobileServiceSyncHandler.
      this.todoTable = client.GetSyncTable<TodoItem>();

    此代码使用 MobileServiceSQLiteStore 类创建一个新的本地 SQLite 数据库。This code creates a new local SQLite database using the MobileServiceSQLiteStore class.

    DefineTable 方法在本地存储中创建一个与所提供类型的字段匹配的表。The DefineTable method creates a table in the local store that matches the fields in the provided type. 该类型无需包括远程数据库中的所有列。The type doesn't have to include all the columns that are in the remote database. 可以只存储列的子集。It is possible to store a subset of columns.

  • TodoItemManager 中的 todoTable 字段是 IMobileServiceSyncTable 类型,而不是 IMobileServiceTable 类型 。The todoTable field in TodoItemManager is an IMobileServiceSyncTable type instead of IMobileServiceTable. 此类使用本地数据库进行所有创建、读取、更新和删除 (CRUD) 表操作。This class uses the local database for all create, read, update, and delete (CRUD) table operations. 通过调用 IMobileServiceSyncContext 中的 PushAsync,确定这些更改推送到移动应用后端的时间 。You decide when those changes are pushed to the Mobile App backend by calling PushAsync on the IMobileServiceSyncContext. 对于调用 PushAsync 时客户端应用修改的所有表,该同步上下文通过跟踪和推送这些表中的更改来帮助保持表关系 。The sync context helps preserve table relationships by tracking and pushing changes in all tables a client app has modified when PushAsync is called.

    调用以下 SyncAsync 方法来与移动应用后端进行同步:The following SyncAsync method is called to sync with the Mobile App backend:

      public async Task SyncAsync()
          ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
              await this.client.SyncContext.PushAsync();
              await this.todoTable.PullAsync(
          catch (MobileServicePushFailedException exc)
              if (exc.PushResult != null)
                  syncErrors = exc.PushResult.Errors;
          // Simple error/conflict handling.
          if (syncErrors != null)
              foreach (var error in syncErrors)
                  if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
                      //Update failed, reverting to server's copy.
                      await error.CancelAndUpdateItemAsync(error.Result);
                      // Discard local change.
                      await error.CancelAndDiscardItemAsync();
                  Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.",
                      error.TableName, error.Item["id"]);

    此示例使用默认同步处理程序的简单错误处理。This sample uses simple error handling with the default sync handler. 实际的应用程序使用自定义的 IMobileServiceSyncHandler 实现处理各种错误,如网络状况和服务器冲突。A real application would handle the various errors like network conditions and server conflicts by using a custom IMobileServiceSyncHandler implementation.

脱机同步注意事项Offline sync considerations

在此示例中,仅在启动和请求同步时才调用 SyncAsync 方法。In the sample, the SyncAsync method is only called on start-up and when a sync is requested. 若要在 Android 或 iOS 应用中启动同步,请下拉项目列表;对于 Windows,请使用“同步” 按钮。To initiate a sync in an Android or iOS app, pull down on the items list; for Windows, use the Sync button. 在实际的应用程序中,还可以在网络状态发生更改时触发此同步功能。In a real-world application, you could also make the sync trigger when the network state changes.

如果对一个表执行拉取操作,并且该表具有由上下文跟踪的未完成的本地更新,那么该拉取操作自动触发之前的上下文推送操作。When a pull is executed against a table that has pending local updates tracked by the context, that pull operation automatically triggers a preceding context push. 在此示例中刷新、添加和完成项目时,可省略显式 PushAsync 调用。When refreshing, adding, and completing items in this sample, you can omit the explicit PushAsync call.

在所提供的代码中,将查询远程 TodoItem 表中的所有记录,但它还可以筛选记录,只需将查询 ID 和查询传递给 PushAsync即可。In the provided code, all records in the remote TodoItem table are queried, but it is also possible to filter records by passing a query id and query to PushAsync. 有关详细信息,请参阅 Azure 移动应用中的脱机数据同步 中的 增量同步部分。For more information, see the section Incremental Sync in Offline Data Sync in Azure Mobile Apps.

运行客户端应用Run the client app

现已启用脱机同步,可在每个平台上至少运行一次客户端应用程序,以填充本地存储数据库。With offline sync now enabled, run the client application at least once on each platform to populate the local store database. 稍后,模拟脱机场景,并在应用处于脱机状态时修改本地存储中的数据。Later, simulate an offline scenario and modify the data in the local store while the app is offline.

更新客户端应用的同步行为Update the sync behavior of the client app

本节对客户端项目进行修改,通过对后端使用无效的应用程序 URL 来模拟脱机场景。In this section, modify the client project to simulate an offline scenario by using an invalid application URL for your backend. 或者,可以将设备移到“飞行模式”来关闭网络连接。Alternatively, you can turn off network connections by moving your device to "Airplane mode." 添加或更改数据项时,这些更改保存在本地存储中,但在重新建立连接之前,这些更改不会同步到后端数据存储中。When you add or change data items, these changes are held in the local store, but not synced to the backend data store until the connection is re-established.

  1. 在解决方案资源管理器中,从 Portable 项目打开 Constants.cs 项目文件,然后更改 ApplicationURL 的值,使其指向无效的 URL:In the Solution Explorer, open the Constants.cs project file from the Portable project and change the value of ApplicationURL to point to an invalid URL:

     public static string ApplicationURL = @"https://your-service.chinacloudsites.cn/";
  2. 从 Portable 项目打开 TodoItemManager.cs 文件,然后在 SyncAsync 的 try...catch 块中为 Exception 基类添加一个 catch 。Open the TodoItemManager.cs file from the Portable project, then add a catch for the base Exception class to the try...catch block in SyncAsync. catch 块会将异常消息写入控制台,如下所示:This catch block writes the exception message to the console, as follows:

         catch (Exception ex)
             Console.Error.WriteLine(@"Exception: {0}", ex.Message);
  3. 生成并运行客户端应用。Build and run the client app. 添加一些新的项。Add some new items. 请注意,每次尝试与后端同步时,都会在控制台中记录异常。Notice that an exception is logged in the console for each attempt to sync with the backend. 这些新项目在推送到移动后端之前,只存在于本地存储中。These new items exist only in the local store until they can be pushed to the mobile backend. 客户端应用的行为就像它已连接到支持所有创建、读取、更新、删除 (CRUD) 操作的后端一样。The client app behaves as if it is connected to the backend, supporting all create, read, update, delete (CRUD) operations.

  4. 关闭应用程序并重新启动它,以验证你创建的新项目是否已永久保存到本地存储中。Close the app and restart it to verify that the new items you created are persisted to the local store.

  5. (可选)使用 Visual Studio 查看 Azure SQL 数据库表,看看后端数据库中的数据是否未更改。(Optional) Use Visual Studio to view your Azure SQL Database table to see that the data in the backend database has not changed.

    在 Visual Studio 中,打开“服务器资源管理器” 。In Visual Studio, open Server Explorer. 导航到“Azure” ->“SQL 数据库” 中的数据库。Navigate to your database in Azure->SQL Databases. 右键单击数据库并选择“在 SQL Server 对象资源管理器中打开” 。Right-click your database and select Open in SQL Server Object Explorer. 现在便可以浏览 SQL 数据库表及其内容。Now you can browse to your SQL database table and its contents.

更新客户端应用以重新连接移动后端Update the client app to reconnect your mobile backend

本节将应用重新连接到移动后端,以模拟重新回到联机状态的应用。In this section, reconnect the app to the mobile backend, which simulates the app coming back to an online state. 执行刷新手势时,数据同步到移动后端。When you perform the refresh gesture, data is synced to your mobile backend.

  1. 重新打开 Constants.cs。Reopen Constants.cs. 更正 applicationURL ,使其指向正确的 URL。Correct the applicationURL to point to the correct URL.

  2. 重新生成并运行客户端应用。Rebuild and run the client app. 该应用在启动后将尝试与移动应用后端进行同步。The app attempts to sync with the mobile app backend after launching. 验证调试控制台中是否未记录任何异常。Verify that no exceptions are logged in the debug console.

  3. (可选)使用 SQL Server 对象资源管理器或 REST 工具(如 Fiddler 或 Postman)查看更新后的数据。(Optional) View the updated data using either SQL Server Object Explorer or a REST tool like Fiddler or Postman. 请注意,数据已在后端数据库和本地存储之间进行同步。Notice the data has been synchronized between the backend database and the local store.

    请注意,数据已在数据库和本地存储之间进行同步,并包含在应用断开连接时添加的项目。Notice the data has been synchronized between the database and the local store and contains the items you added while your app was disconnected.

其他资源Additional Resources