Skip to content

Best Practices

There are additional best practices to consider when developing offline applications.

In the following, Offline OData service refers to the component in the mobile service that moves data between the back-end OData service and the client offline store.

Best Practices for Defining Queries

  • Using /CollectionA and /CollectionB versus /CollectionA?$expand=CollectionB

    This best practice depends on the OData service and the data in those entity sets. A defining query with $expand can be broken up into multiple defining queries without $expand only if the association in the metadata defines a referential constraint.

    It is generally preferable to use $expand in OData queries for relationships, but this may not always provide the best performance for Offline OData:

    • Lack of support for deltas with $expand The Offline OData service does not support OData service deltas for defining queries with expands directly. If a defining query contains $expand there are two possibilities, with respect to deltas:
      1. Using the Offline OData service delta computation.
      2. Disabling the Offline OData service delta computation causes a full download of the data.
    • Data duplication Sometimes an application requires more than one defining query to get all the data and relationships because their data does not form a tree rooted from a single set. In such a case, many defining queries may have to expand to the same sets, creating duplicate entities that are retrieved from the OData service. Splitting the defining queries up resolves this problem because each entity is downloaded only once, and the Offline OData service computes the relationships using the referential constraints.
    • Shared data You may have a set of data that is shared by all users but is reference-able by user specific data. In this case, you want to separate the shared data into a separate defining query from the user specific data. The relationships between the shared data and the user defined data are computed by the Offline OData service using the referential constraints, however, download the shared data only once for all users, instead of for each user.
  • $top and $skip Developers should not use $top or $skip in their defining queries. The amount of data retrieved from the OData service should be controlled using $filter or other back end-specific means (such as based on the currently authenticated user). If the use of $top and $skip is intended to break up how much data the OData service can send at one time, then the OData service should be changed to use server driven paging instead (that is, return next links). The developer is free to use $top and $skip when executing local queries.

Provisioning the Device

Multiple stores – an application can use multiple offline stores. A store can only be used for one OData service, and it is a best practice that only one store is used per OData service. Define the stores using that are then passed to OfflineODataProvider.


Client may report various errors. Typical reasons for errors to consider include but not limited to:

  • Incorrect service root

  • Incorrect defining queries

  • Incorrect user input (resulting in invalid data in requests)

  • Incorrect back end configuration in the mobile service

  • Incorrect application configuration in the mobile service

  • Back-end OData service going down

  • The mobile service going down

  • Connectivity between the mobile service and the back end being unstable

When errors happen during upload and download, you should check mobile service log as well as ErrorArchive on the client to diagnose the issue and figure out the resolution.

If any error happens during the initial download of data (opening the offline store for the first time), the offline store will automatically clean up the erroneous state/data, allowing the offline application to start over. In this case you should check error message reported by the client or the mobile service log in order to correct the issue (for example, the client is using incorrect service root or defining queries).

Last update: October 30, 2020