Docs Menu

Flexible Sync - .NET SDK

On this page

  • Overview
  • Manage Your Subscriptions
  • Get Subscriptions
  • Add a Query to the Set Of Subscriptions
  • Update Subscriptions with a New Query
  • Remove Subscriptions
  • Wait for Subscription Changes to Sync

Flexible Sync uses subscriptions and permissions to determine which data to sync with your Realm app.

To use Flexible Sync in a .NET application:

You can add, update, and remove query subscriptions to determine which data syncs to the client device.

Important

Flexible Sync is currently in preview. We encourage you to try out the feature and give feedback, but please be aware that:

  • Configuration details may change.
  • SDK API implementation details may change.

We do not recommend using Flexible Sync in production applications while it is still in preview.

Note
Flexible Sync Prerequisites

Enabling Flexible Sync in Your Realm Application requires the following:

  • A non-sharded MongoDB Atlas cluster running MongoDB 5.0 or greater
  • A Realm app without Partition-Based Sync enabled. While Flexible Sync is in preview, you cannot use Flexible Sync & Partition-Based Sync in the same Realm app.
Note
Realm .NET SDK Version Requirement

In addition to the requirements above, you must use Realm .NET version 10.9.0 or greater in order to use Flexible Sync in your .NET client application.

When configuring Flexible Sync on the backend, you specify which fields your client application can query. In the client application, use the subscriptions API to manage a set of subscriptions to specific queries on queryable fields.

You can:

  • Get a list of all subscriptions
  • Add subscriptions
  • Check subscription state
  • Update a subscription with a new query
  • Remove individual subscriptions or all subscriptions of a type

When the data matches the subscription, and the authenticated user has the appropriate permissions, Realm syncs the backend data with the client app.

You can specify a string name for your subscription. If you do not give your subscription a name, the name is set to null.

When you create a subscription, Realm looks for data matching a query on a specific object type. In your Flexible Sync subscriptions, you can have subscriptions on several different object types or several queries on the same object type.

Important
Object Links

You must add both an object and its linked object to the subscription set to see a linked object.

If your subscription results contain an object with a property that links to an object not contained in the results, the link appears to be nil. There is no way to distinguish whether that property's value is legitimately nil, or whether the object it links to exists but is out of view of the query subscription.

When using flexible sync, you can access a SubscriptionSet, a collection of subscriptions, through the Realm.Subscriptions property.

var subscriptions = realm.Subscriptions;

You can use this subscriptions set to add queries to this list of subscriptions and update existing subscriptions, as shown in the examples below.

You must perform all mutations on the subscriptions set within an update block. To create an update block, call the SubscriptionSet.Update(). method.

Within the delegate, call the SubscriptionSet.Add() method on the SubscriptionSet to add a query to the subscription.

Important

Flexible Sync does not support all the operators available in Realm Query Language. See Flexible Sync RQL Limitations for details.

The Add() method takes two arguments, a query and an optional SubscriptionOptions object.

Create the query argument using the query engine.

SubscriptionOptions contains additional configuration for your subscription:

  • a Name string field
  • a UpdateExisting boolean field.

If UpdateExisting is true, adding a subscription with an existing name will replace the existing query with the new query. However, if you set UpdateExisting to false, adding a subscription with an existing name but a different query throws an exception. UpdateExisting defaults to true.

Note
Duplicate Subscriptions

If you add a duplicate unnamed subscription with the same query, Realm automatically removes it; adding an identical named subscription is a no-op. Therefore, in both cases, duplicate subscriptions are ignored.

You can add a single query, or batch multiple queries within a SubscriptionSet.Update block. Performing query updates is an expensive operation on the server. We strongly advise designing your application to minimize updates. You can do this by creating all subscriptions in a single update block the first time the user launches the app and batching any follow-up changes to the subscription set.

In the example below, we subscribe to three queries.

realm.Subscriptions.Update(() =>
{
// subscribe to all long running tasks, and give the subscription the name 'longRunningTasksSubscription'
var longRunningTasksQuery = realm.All<Task>().Where(t => t.Status == "completed" && t.ProgressMinutes > 120 );
realm.Subscriptions.Add(longRunningTasksQuery, new SubscriptionOptions() { Name = "longRunningTasks" });
// subscribe to all of Ben's Task objects
realm.Subscriptions.Add(realm.All<Task>().Where(t => t.Owner == "Ben"));
// subscribe to all Teams, and give the subscription the name 'teamsSubscription' and throw an error if a new query is added to the team subscription
realm.Subscriptions.Add(realm.All<Team>(), new SubscriptionOptions() { Name = "teams", UpdateExisting = false });
});

You can update a named subscription with a new query. To update a subscription's query, pass the new query and a subscription option with the name of the subscription that you want to update to the SubscriptionSet.Add() method. Like adding a new subscription, you must update a subscription within an update block by calling SubscriptionSet.Update() method.

Note

Updating an unnamed subscription is not possible. Alternatively, you can delete the unnamed subscription, and create a new subscription with the desired query.

In the following example, long running tasks are re-defined to be any tasks that have taken more than 130 minutes.

realm.Subscriptions.Update(() =>
{
var updatedLongRunningTasksQuery = realm.All<Task>().Where(t => t.Status == "completed" && t.ProgressMinutes > 130);
realm.Subscriptions.Add(updatedLongRunningTasksQuery, new SubscriptionOptions() { Name = "longRunningTasks" });
});
Note

Attempting to update a subscription that has the SubscriptionOptions.UpdateExisting field set to false will throw an exception.

To remove subscriptions from the subscription set, you can:

  • Remove a single subscription with the given query
  • Remove a single subscription with the given name
  • Remove a single subscription with the given subscription
  • Remove all subscriptions of a specific type
  • Remove all subscriptions

When you remove a subscription query, the server also removes synced data from the client device.

Within an update block, you can remove a specific subscription by query. Pass the query to the Remove() method on the SubscriptionSet.

In the following example, the subscription to tasks with an owner named 'Ben' is removed from the subscriptions set.

realm.Subscriptions.Update(() =>
{
// remove a subscription by it's query
var query = realm.All<Task>().Where(t => t.Owner == "Ben");
realm.Subscriptions.Remove(query);
});

Within an update block, you can remove a specific subscription by name. Pass the name to the Remove() method on the SubscriptionSet.

realm.Subscriptions.Update(() =>
{
// remove a named subscription
var subscriptionName = "longRunningTasksSubscription";
realm.Subscriptions.Remove(subscriptionName);
});

Within an update block, you can remove remove all unnamed subscriptions of a class by passing the class name as a string to the RemoveAll("ClassName") method. The RemoveAll() method has an optional second argument that is a boolean, removedName, which also removes the named subscriptions if it is set to true. removedName is set to false by default.

Alternatively, you can remove all unnamed subscriptions of an object type with RemoveAll(). The RemoveAll<Type>() method has an optional boolean removedName argument which also removes the named subscriptions if it is set to true. removedName is set to false by default.

realm.Subscriptions.Update(() =>
{
// remove all subscriptions of the "Team" Class Name
realm.Subscriptions.RemoveAll("Team");
// Alernatively, remove all subscriptions of the "Team" object type
realm.Subscriptions.RemoveAll<Team>();
});

Within an update block, you can remove all unnamed subscriptions from the subscriptions set. Call the RemoveAll() method on the SubscriptionSet. The RemoveAll() method has an optional boolean removedName argument which also removes the named subscriptions if it is set to true. removedName is set to false by default.

realm.Subscriptions.Update(() =>
{
// remove all subscriptions, including named subscriptions
realm.Subscriptions.RemoveAll(true);
});

Mutating the subscription set within an update block is only one part of changing a subscription. After the local subscription change, the realm synchronizes with the server to resolve any updates to the data due to the subscription change. This could mean adding or removing data from the synced realm.

Use the SubscriptionSet.WaitForSynchronizationAsync() method to wait for the server to acknowledge this set of subscriptions. If the server rejects the change, the SubscriptionSetState will be an error state, and an exception will be thrown.

An exception may occur if:

  • an unsupported query is subscribed to. Subscribing to an unsupported query will pause synchronization. To resume synchronization, remove the unsupported query.
  • you are performing an invalid action, such as adding an object that does not match a subscription. This triggers a client reset: data is erased from the realm, and a new copy of the data is created without any subscriptions in the set.
// Wait for the server to acknowledge the subscription change and return all objects
// matching the query
try
{
await realm.Subscriptions.WaitForSynchronizationAsync();
}
catch (SubscriptionException ex)
{
// do something in response to the exception or log it
Console.WriteLine($@"The subscription set's state is Error and synchronization is paused: {ex.Message}");
}
←  Sync Changes Between Devices - .NET SDKCall a Function - .NET SDK →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.