Skip to content

Defining Queries

A defining query is a read query that targets the OData service associated with the offline store and retrieves a subset of the endpoint data. You can define multiple defining queries for each endpoint.

Defining queries retrieve data from the OData service that is sent to the client, either during initialization of the offline store or during a download.

Defining queries are set up in both the application source code and in the application configuration files. In Java, use the addDefiningQuery method from the OfflineODataProvider class with a name and a query. In Swift, use the add() method from OfflineODataProvider class with an instance of the OfflineODataDefiningQuery class constructed with a name, a query, and a flag for whether or not automatically retrieving streams. The example below demonstrates how the defining queries retrieve all information for one event.

// Expand is needed to create a many-to-many relationship between Event and Feature
// since there is no referential constraint defined on the relationship.
// Data sharing should be enabled as all users see the same information
offlineODataProvider.addDefiningQuery(
    new OfflineODataDefiningQuery("Events_10000",
    "/Events?$filter=EventID eq 10000L&$expand=Features",
    false));
// One-to-many relationship between Event and Session is built via
// referential constraint. Data sharing should be enabled
offlineODataProvider.addDefiningQuery(
    new OfflineODataDefiningQuery("Sessions_10000",
    "/Sessions?$filter=EventID eq 10000L",
    false));
// Data sharing should be enabled
offlineODataProvider.addDefiningQuery(
    new OfflineODataDefiningQuery("Tracks_10000",
    "/Tracks?$filter=EventID eq 10000L",
    false));
// User Specific data; data sharing should be off
offlineODataProvider.addDefiningQuery(
    new OfflineODataDefiningQuery("UserSessionAgendas",
    "/UserSessionAgendas?$filter=EventID eq 10000L",
    false));
// Data sharing should be enabled.
offlineODataProvider.addDefiningQuery(
    new OfflineODataDefiningQuery("Features",
    "/Features",
    false));
/// Expand is needed to create a many-to-many relationship between Event and Feature
/// since there is no referential constraint defined on the relationship.
/// Data sharing should be enabled as all users see the same information
try provider.add(definingQuery: OfflineODataDefiningQuery(name: "Events_10000",
    query: "/Events?$filter=EventID eq 10000L&$expand=Features",
    automaticallyRetrievesStreams: false))

/// One-to-many relationship between Event and Session is built via referential constraint.
/// Data sharing should be enabled
try provider.add(definingQuery: OfflineODataDefiningQuery(name: "Sessions_10000",
    query: "/Sessions?$filter=EventID eq 10000L",
    automaticallyRetrievesStreams: false))

/// Data sharing should be enabled
try provider.add(definingQuery: OfflineODataDefiningQuery(name: "Tracks_10000",
    query: "/Tracks?$filter=EventID eq 10000L",
    automaticallyRetrievesStreams: false))

/// User Specific data; data sharing should be off
try provider.add(definingQuery: OfflineODataDefiningQuery(name: "UserSessionAgendas",
    query: "/UserSessionAgendas?$filter=EventID eq 10000L",
    automaticallyRetrievesStreams: false))

/// Data sharing should be enabled
try provider.add(definingQuery: OfflineODataDefiningQuery(name: "Features",
    query: "/Features",
    automaticallyRetrievesStreams: false))

In the application configuration file, reference each query using the same name as the one written in the source code (the first parameter to the OfflineODataDefiningQuery constructor), as shown in the following example:

[defining_query]
name=Events_10000
is_shared_data=Y
download_interval=10
track_deltas=AUTO
delta_token_lifetime=36000

[defining_query]
name=UserSessionsAgendas
is_shared_data=N

In the example, the defining query Events_10000 is declared as shareable, which means that the event and related features can be accessed by all users.

Usually, you'll specify defining queries before opening the offline store for the first time, but they can also be added or removed afterwards if appropriate. You can use the getDefiningQueries method from the OfflineODataProvider class to fetch all existing defining queries.

Keep the following in mind when writing defining queries:

  • Currently, only defining queries where the resource path identifies an entity set or entity type instance (a single entity) are supported.

  • Shared defining query names must be unique, and must be identical on both the client and server. Otherwise, expected settings will not be applied to the correct defining query and the query will be using the default settings instead.

  • If you are using a mix of delta-enabled and non-delta-enabled defining queries, and you are using referential constraints to build relationships, the dependent entity in a relationship cannot be in a delta-enabled defining query if the principal entity is in a non-delta enabled-relationship. For example, say you have two defining queries, Events and Sessions (based on the sample metadata). Since there is a referential constraint between them and no expands are specified, the mobile services automatically uses the referential constraints to build relationships. The events are the principal entities and the sessions are the dependent entities. If the Events defining query is not delta-enabled, then the Sessions defining query must not be delta-enabled. However, if the Events defining query is delta-enabled, the Sessions defining query may or may not be delta-enabled.

  • If you are not using deltas, you can use the same entity sets in more than one defining query, but you cannot perform a selective download of one of those defining queries without the others.

  • If you are using a mix of delta-enabled and non-delta enabled defining queries, you cannot use the same entity set in both a delta-enabled and a non-delta enabled defining query, either directly referenced in the resource path or through an $expand.

Removing Defining Queries

You can always remove a stream-defining query. For non-stream-defining queries, before opening the offline store, if a defining query is specified for the first time, then you can remove it immediately. After opening the offline store, by default configuration, neither existing defining queries, nor new specifying defining queries can be removed. To remove a defining query and its entities in the local store, you need to set allow_defining_query_removal to Y. This will allow the server and local store to keep track of the mapping between defining queries and entities. If you do not need to remove any general defining queries, leave allow_defining_query_removal as N for better performance. Turning allow_defining_query_removal on or off will cause the server to reinitialize the offline store for the client during a download. This will take more time than the normal download, and if the client has any pending changes, they will not take place until pending changes are uploaded or deleted.

Using Defining Queries to Build Entity Relationships

To build relationships in your application, you can use $expand in queries, referential constraints, or a combination of the two.

  • $expand in queries

    Use $expand in queries to build relationships between entity sets only if you are not tracking deltas, or if you are tracking deltas using the mobile services. You cannot use $expand in queries if you are tracking deltas using the OData service.

  • Referential constraints

    If you are tracking deltas using the OData service and require entity relationships in the offline store, you cannot use $expand in queries but instead must have associations with referential constraints. Ensure that each defining query references a single entity set. The mobile services detects the associations with referential constraints and uses referential constraints to build the relationships between the entity sets selected in your defining queries.

    For example, the sample metadata document has an association between Event and Session, called Event_Session_One_Many0, which defines a referential constraint. If you specify two defining queries, /Events and /Sessions, the server uses the referential constraint defined in the association Event_Session_One_Many0 to build the relationship between the Events and Sessions entity sets in the offline store.

  • Combining referential constraints and $expand in queries

    When you use an $expand to build relationships between two top-level entity sets, an association set is implicitly referenced. For example, /Events?$expand=Sessions implicitly references the Event_Session_One_Many0Set association set. The mobile services allows you to mix referential constraints and $expand to build relationships.

    Consider the following example, which uses entity sets from the sample metadata:

    ~/Events?$expand=Sessions
    ~/Tracks
    

Relationships between events and sessions are computed using $expand, and relationships between events and track are computed using referential constraints.

However, you cannot mix referential constraints and $expand for the same implicitly referenced association set. In the example below, relationships between events in Canada and their sessions are built using $expand, where the Event_Session_One_Many0Set association set is implicitly referenced. Although there is an Event_Session_One_Many0 association with referential constraint between the Event and Session entity type, the referential constraint will not be used by the second and the third defining query to build other relationships, since the referential constraint also implicitly references the same association set. As a result, relationships between events in the US and their sessions are not built. Hence, only for events in Canada can one use the Sessions navigation property to get associated sessions. For events in the US, one must use the EventID property in a filter to get the associated sessions.

~/Events?$expand=Sessions&$filter=Country eq 'CAN'
~/Events?$filter=Country eq 'US'
~/Sessions
~/Tracks

Tip

This is not an exhaustive list of ways to build relationships. The choice of defining queries is highly dependent on the needs of the offline application.

The table below lists parameters that can be used to configure defining queries in an application configuration file.

Parameter Value Notes
name Valid String (Required) Name of the defining query.endpoint data.
is_shared_data N or Y Whether the data is shared among different clients or users.
  • N Some data is not shared among multiple client databases.
  • Y Data is shared among multiple client databases.

The default value is N.

refresh_interval NNN The interval time, in minutes, between downloads of the shared data.

The default is 15 minutes.

track_deltas AUTO or ALWAYS or NEVER How to track OData deltas.
  • AUTO If the OData service supports delta change tracking on the defining query, the delta links returned are used when downloading the data. If the OData service does not support delta change tracking on the defining query, the mobile service tracks the changes so that only changed data is exchanged between the client and the mobile services.
  • ALWAYS Sets the mobile services to always track delta changes. This option is equivalent to AUTO if the OData service does not support delta change tracking on the defining query.
  • NEVER Sets the mobile services to never track delta changes. If the OData service supports delta change tracking, the delta links returned by the OData service are used when downloading data, even if this option is specified.

The default value is AUTO.

delta_token_lifetime NNN The time, in minutes, until the OData delta token expires. While a token is valid, only changed data is downloaded to the offline store. When the delta token expires, the entire data set is replaced.

The default is 72000 minutes (50 days).


Last update: June 7, 2022