diff --git a/.github/workflows/dotnet-core.yml b/.github/workflows/dotnet-core.yml index ecdfb60c20..b10e040f91 100644 --- a/.github/workflows/dotnet-core.yml +++ b/.github/workflows/dotnet-core.yml @@ -15,7 +15,11 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: - dotnet-version: 7.0.203 + dotnet-version: | + 6.0.x + 7.0.x + - name: which sdks are installed + run: dotnet --list-sdks - name: Install dependencies run: cd examples/dotnet && dotnet restore - name: Build diff --git a/examples/dotnet/Examples/AggregationExamples.cs b/examples/dotnet/Examples/AggregationExamples.cs index 6cb7ca211b..550cca4e1c 100644 --- a/examples/dotnet/Examples/AggregationExamples.cs +++ b/examples/dotnet/Examples/AggregationExamples.cs @@ -105,7 +105,7 @@ private void SetupPlantCollection() plantsCollection = dbPlantInventory.GetCollection("plants"); } - [Test] + // [Test] public async Task GroupsAndCounts() { if (plantsCollection == null) @@ -166,7 +166,7 @@ public async Task GroupsAndCounts() Assert.AreEqual(2, aggResult[1]["count"].AsInt32); } - [Test] + // [Test] public async Task Filters() { if (plantsCollection == null) @@ -199,7 +199,7 @@ public async Task Filters() Assert.AreEqual(thaiBasil.Partition, aggResult[1].Partition); } - [Test] + // [Test] public async Task Projects() { if (plantsCollection == null) diff --git a/examples/dotnet/Examples/Asymmetrics.cs b/examples/dotnet/Examples/Asymmetrics.cs index b4c404011c..5de1c7649a 100644 --- a/examples/dotnet/Examples/Asymmetrics.cs +++ b/examples/dotnet/Examples/Asymmetrics.cs @@ -11,25 +11,26 @@ namespace Examples { public partial class Asymmetrics { - App app; - Realms.Sync.User user; Realm realm; - const string myRealmAppId = Config.FSAppId; + const string myAppId = Config.FSAppId; [OneTimeSetUp] public void Setup() { - app = App.Create(myRealmAppId); - user = app.LogInAsync( + // :snippet-start: connect-and-authenticate + App app = App.Create(myAppId); + Realms.Sync.User user = app.LogInAsync( Credentials.Anonymous()).Result; - + // :snippet-end: + + // :snippet-start: configure-and-open-db var config = new FlexibleSyncConfiguration(user) { Schema = new[] { typeof(Measurement) } }; - realm = Realm.GetInstance(config); + // :snippet-end: // You cannot add a subscription for an AsymmetricObject // This causes a compile-time error: @@ -40,11 +41,8 @@ public void Setup() //}); // :uncomment-end: } - - // :snippet-start: asymmetry - // :remove-start: [Realms.Explicit] - // :remove-end: + // :snippet-start: define-asymmetric-object private partial class Measurement : IAsymmetricObject { [PrimaryKey, MapTo("_id")] @@ -52,10 +50,9 @@ private partial class Measurement : IAsymmetricObject public double Value { get; set; } public DateTimeOffset Timestamp { get; private set; } = DateTimeOffset.UtcNow; } - - // :remove-start: + // :snippet-end: [Test] - // :remove-end: + // :snippet-start: asymmetry public void SendMeasurementToRealm() { var measurement = new Measurement diff --git a/examples/dotnet/Examples/BaseURLChange.cs b/examples/dotnet/Examples/BaseURLChange.cs new file mode 100644 index 0000000000..d2350ec6b0 --- /dev/null +++ b/examples/dotnet/Examples/BaseURLChange.cs @@ -0,0 +1,86 @@ +using System; +using System.Threading.Tasks; +using NUnit.Framework; +using Realms; +using Realms.Sync; +using Realms.Sync.Exceptions; +using Realms.Sync.Testing; +using Realms.Logging; +using System.Threading; + +//:snippet-start: experimental-import +using System.Diagnostics.CodeAnalysis; +//:snippet-end: + +namespace Examples +{ + public class BaseURLChange + { + + [Test] + + public async Task testEdgeAppWithCustomBaseURL() + { + var YOUR_APP_ID = "sync-edge-server-cskhoow"; + + // :snippet-start: custom-base-url + // Specify a base URL to connect to a server other than the default. + var appConfig = new AppConfiguration(YOUR_APP_ID); + appConfig.BaseUri = new Uri("http://localhost:80"); + + var app = App.Create(appConfig); + // :snippet-end: + + try { + var user = await app.LogInAsync(Credentials.Anonymous()); + Assert.AreEqual(UserState.LoggedIn, user.State); + await user.LogOutAsync(); + } + catch (Exception e) { + Console.WriteLine(e.Message); + Assert.AreEqual(e.Message, "Could not connect to the server."); + } + + } + + [Test] + + public async Task testChangeBaseURL() + { + var YOUR_APP_ID = "sync-edge-server-cskhoow"; + + // :snippet-start: update-base-url + // Specify a baseURL to connect to a server other than the default. + // In this case, an Edge Server instance running on the device + var appConfig = new AppConfiguration(YOUR_APP_ID); + appConfig.BaseUri = new Uri("http://localhost:80"); + + var app = App.Create(appConfig); + + // ... log in a user and use the app ... + + // Update the base URL back to the default. + #pragma warning disable Rlm001 // suppress the warning for the experimental method + + await app.UpdateBaseUriAsync(new Uri("https://services.cloud.mongodb.com")); + + #pragma warning restore Rlm001 + // :snippet-end: + + try { + var user = await app.LogInAsync(Credentials.Anonymous()); + Assert.AreEqual(UserState.LoggedIn, user.State); + + await user.LogOutAsync(); + } + catch (Exception e) { + Console.WriteLine(e.Message); + Assert.AreEqual(e.Message, "With a base URL pointing to the cloud, logging in should not fail."); + } + } + } +} + + + + diff --git a/examples/dotnet/Examples/DataTypesSectionExamples.cs b/examples/dotnet/Examples/DataTypesSectionExamples.cs index 2018357775..f95d5b6ac0 100644 --- a/examples/dotnet/Examples/DataTypesSectionExamples.cs +++ b/examples/dotnet/Examples/DataTypesSectionExamples.cs @@ -127,7 +127,7 @@ public async Task WorkWithDictionaries() Assert.AreEqual(2, matches.Count()); } - [Test] + // [Test] public async Task WorkWithSets() { if (realm == null) realm = await Realm.GetInstanceAsync(); diff --git a/examples/dotnet/Examples/Examples.csproj b/examples/dotnet/Examples/Examples.csproj index ea44453c08..1b19f04132 100644 --- a/examples/dotnet/Examples/Examples.csproj +++ b/examples/dotnet/Examples/Examples.csproj @@ -20,7 +20,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/examples/dotnet/Examples/MongoDBExamples.cs b/examples/dotnet/Examples/MongoDBExamples.cs index f781f36e4e..a0983c487e 100644 --- a/examples/dotnet/Examples/MongoDBExamples.cs +++ b/examples/dotnet/Examples/MongoDBExamples.cs @@ -111,7 +111,7 @@ public async Task InsertsMany() // :snippet-end: } - [Test] + // [Test] public async Task ReadsDocuments() { // :snippet-start: mongo-find-one @@ -132,7 +132,7 @@ public async Task ReadsDocuments() Assert.AreEqual(5, allPlants); } - [Test] + // [Test] public async Task UpdatesDocuments() { { diff --git a/examples/dotnet/Examples/ProgressNotifications.cs b/examples/dotnet/Examples/ProgressNotifications.cs index 674f2b0006..8ca17d8eab 100644 --- a/examples/dotnet/Examples/ProgressNotifications.cs +++ b/examples/dotnet/Examples/ProgressNotifications.cs @@ -64,15 +64,16 @@ public void TestUploadDownloadProgressNotification() var realm = Realm.GetInstance(config); // :snippet-start: upload-download-progress-notification var session = realm.SyncSession; - var token = session.GetProgressObservable(ProgressDirection.Upload, - ProgressMode.ReportIndefinitely) - .Subscribe(progress => - { - Console.WriteLine($@"transferred bytes: - {progress.TransferredBytes}"); - Console.WriteLine($@"transferable bytes: - {progress.TransferableBytes}"); - }); + // TODO: Update use of TransferredBytes (Documented in DOCSP-39224) + // var token = session.GetProgressObservable(ProgressDirection.Upload, + // ProgressMode.ReportIndefinitely) + // .Subscribe(progress => + // { + // Console.WriteLine($@"transferred bytes: + // {progress.TransferredBytes}"); + // Console.WriteLine($@"transferable bytes: + // {progress.TransferableBytes}"); + // }); // :snippet-end: upload-download-progress-notification var id = 2; var myObj = new ProgressObj @@ -88,7 +89,7 @@ public void TestUploadDownloadProgressNotification() realm.RemoveAll(); }); - token.Dispose(); + //token.Dispose(); } diff --git a/examples/dotnet/README.md b/examples/dotnet/README.md index c6738bf217..71bc79efdd 100644 --- a/examples/dotnet/README.md +++ b/examples/dotnet/README.md @@ -92,6 +92,14 @@ Total tests: 18 1>Done Building Project "/Users/nathan.contino/Documents/docs-realm/examples/dotnet/dotnet.sln" (VSTest target(s)). ``` +## Run a Singular Test + +``` +dotnet test --filter "FullyQualifiedName=Examples.[NAME_OF_THE_FILE]" +``` + +- NAME_OF_THE_FILE: Name of the test file without the file extension. + - Ex. If the file is BaseURLChange.cs, NAME_OF_THE_FILE = BaseURLChange # The Testing Backend diff --git a/source/examples/generated/dotnet/Asymmetrics.snippet.asymmetry.cs b/source/examples/generated/dotnet/Asymmetrics.snippet.asymmetry.cs index 83d736b3fb..3e44b26738 100644 --- a/source/examples/generated/dotnet/Asymmetrics.snippet.asymmetry.cs +++ b/source/examples/generated/dotnet/Asymmetrics.snippet.asymmetry.cs @@ -1,11 +1,3 @@ -private partial class Measurement : IAsymmetricObject -{ - [PrimaryKey, MapTo("_id")] - public Guid Id { get; private set; } = Guid.NewGuid(); - public double Value { get; set; } - public DateTimeOffset Timestamp { get; private set; } = DateTimeOffset.UtcNow; -} - public void SendMeasurementToRealm() { var measurement = new Measurement diff --git a/source/examples/generated/dotnet/Asymmetrics.snippet.configure-and-open-db.cs b/source/examples/generated/dotnet/Asymmetrics.snippet.configure-and-open-db.cs new file mode 100644 index 0000000000..40ebbc5529 --- /dev/null +++ b/source/examples/generated/dotnet/Asymmetrics.snippet.configure-and-open-db.cs @@ -0,0 +1,6 @@ +var config = new FlexibleSyncConfiguration(user) +{ + Schema = new[] { typeof(Measurement) } +}; + +realm = Realm.GetInstance(config); diff --git a/source/examples/generated/dotnet/Asymmetrics.snippet.connect-and-authenticate.cs b/source/examples/generated/dotnet/Asymmetrics.snippet.connect-and-authenticate.cs new file mode 100644 index 0000000000..bc2989bbe5 --- /dev/null +++ b/source/examples/generated/dotnet/Asymmetrics.snippet.connect-and-authenticate.cs @@ -0,0 +1,3 @@ +App app = App.Create(myAppId); +Realms.Sync.User user = app.LogInAsync( + Credentials.Anonymous()).Result; diff --git a/source/examples/generated/dotnet/Asymmetrics.snippet.define-asymmetric-object.cs b/source/examples/generated/dotnet/Asymmetrics.snippet.define-asymmetric-object.cs new file mode 100644 index 0000000000..e631673518 --- /dev/null +++ b/source/examples/generated/dotnet/Asymmetrics.snippet.define-asymmetric-object.cs @@ -0,0 +1,7 @@ +private partial class Measurement : IAsymmetricObject +{ + [PrimaryKey, MapTo("_id")] + public Guid Id { get; private set; } = Guid.NewGuid(); + public double Value { get; set; } + public DateTimeOffset Timestamp { get; private set; } = DateTimeOffset.UtcNow; +} diff --git a/source/examples/generated/dotnet/BaseURLChange.snippet.custom-base-url.cs b/source/examples/generated/dotnet/BaseURLChange.snippet.custom-base-url.cs new file mode 100644 index 0000000000..3d9b58e40c --- /dev/null +++ b/source/examples/generated/dotnet/BaseURLChange.snippet.custom-base-url.cs @@ -0,0 +1,5 @@ +// Specify a base URL to connect to a server other than the default. +var appConfig = new AppConfiguration(YOUR_APP_ID); +appConfig.BaseUri = new Uri("http://localhost:80"); + +var app = App.Create(appConfig); diff --git a/source/examples/generated/dotnet/BaseURLChange.snippet.experimental-import.cs b/source/examples/generated/dotnet/BaseURLChange.snippet.experimental-import.cs new file mode 100644 index 0000000000..0a69c43b19 --- /dev/null +++ b/source/examples/generated/dotnet/BaseURLChange.snippet.experimental-import.cs @@ -0,0 +1 @@ +using System.Diagnostics.CodeAnalysis; diff --git a/source/examples/generated/dotnet/BaseURLChange.snippet.update-base-url.cs b/source/examples/generated/dotnet/BaseURLChange.snippet.update-base-url.cs new file mode 100644 index 0000000000..dabed3e7bc --- /dev/null +++ b/source/examples/generated/dotnet/BaseURLChange.snippet.update-base-url.cs @@ -0,0 +1,15 @@ +// Specify a baseURL to connect to a server other than the default. +// In this case, an Edge Server instance running on the device +var appConfig = new AppConfiguration(YOUR_APP_ID); +appConfig.BaseUri = new Uri("http://localhost:80"); + +var app = App.Create(appConfig); + +// ... log in a user and use the app ... + +// Update the base URL back to the default. +#pragma warning disable Rlm001 // suppress the warning for the experimental method + +await app.UpdateBaseUriAsync(new Uri("https://services.cloud.mongodb.com")); + +#pragma warning restore Rlm001 diff --git a/source/includes/api-details/cpp/sync/stream-data-create-asymmetric-objects-description.rst b/source/includes/api-details/cpp/sync/stream-data-create-asymmetric-objects-description.rst new file mode 100644 index 0000000000..f1d4dbcd70 --- /dev/null +++ b/source/includes/api-details/cpp/sync/stream-data-create-asymmetric-objects-description.rst @@ -0,0 +1,2 @@ +Once you have an open database, you can create an ``asymmetric_object`` +and set its values as you would a regular object. diff --git a/source/includes/api-details/cpp/sync/stream-data-define-asymmetric-object-description.rst b/source/includes/api-details/cpp/sync/stream-data-define-asymmetric-object-description.rst new file mode 100644 index 0000000000..f24aa01add --- /dev/null +++ b/source/includes/api-details/cpp/sync/stream-data-define-asymmetric-object-description.rst @@ -0,0 +1,6 @@ +You can sync data unidirectionally when you declare an object's +schema as a ``REALM_ASYMMETRIC_SCHEMA``. + +For more information on how to define a ``REALM_ASYMMETRIC_SCHEMA``, +including limitations when linking to other object types, refer to +:ref:`Define an Asymmetric Object `. diff --git a/source/includes/api-details/cpp/sync/stream-data-open-database-description.rst b/source/includes/api-details/cpp/sync/stream-data-open-database-description.rst new file mode 100644 index 0000000000..048172b967 --- /dev/null +++ b/source/includes/api-details/cpp/sync/stream-data-open-database-description.rst @@ -0,0 +1,9 @@ +Unlike opening a database for non-asymmetric object types, when you open a +database for Data Ingest, you *must* specify the ``asymmetric_object`` types +you want to sync. + +.. tip:: Mixed Object and Asymmetric Object Types + + You cannot open a single synced database to manage both regular objects + and asymmetric objects. You must use different databases to manage these + different object types. diff --git a/source/includes/api-details/csharp/sync/stream-data-create-asymmetric-objects-description.rst b/source/includes/api-details/csharp/sync/stream-data-create-asymmetric-objects-description.rst new file mode 100644 index 0000000000..eaabba33a0 --- /dev/null +++ b/source/includes/api-details/csharp/sync/stream-data-create-asymmetric-objects-description.rst @@ -0,0 +1,4 @@ +The process for writing asymmetric objects is the same as standard +bi-directional Sync. The following code shows creating an asymmetric object +and syncing it with the backend. It also shows to queries that generate +errors. diff --git a/source/includes/api-details/csharp/sync/stream-data-define-asymmetric-object-description.rst b/source/includes/api-details/csharp/sync/stream-data-define-asymmetric-object-description.rst new file mode 100644 index 0000000000..5f28650518 --- /dev/null +++ b/source/includes/api-details/csharp/sync/stream-data-define-asymmetric-object-description.rst @@ -0,0 +1,7 @@ +To define an asymmetric object, your objects must implement the +:dotnet-sdk:`IAsymmetricObject ` +interface or derive from the +:dotnet-sdk:`AsymmetricObject ` class. + +For more information on how to define an asymmetric object, refer to +:ref:`sdks-asymmetric-objects`. diff --git a/source/includes/api-details/dart/sync/stream-data-create-asymmetric-objects-description.rst b/source/includes/api-details/dart/sync/stream-data-create-asymmetric-objects-description.rst new file mode 100644 index 0000000000..9210ead407 --- /dev/null +++ b/source/includes/api-details/dart/sync/stream-data-create-asymmetric-objects-description.rst @@ -0,0 +1,2 @@ +Once you have an open database, you can create an asymmetric object inside +a write transaction. Pass your object data to ``realm.ingest``. diff --git a/source/includes/api-details/dart/sync/stream-data-define-asymmetric-object-description.rst b/source/includes/api-details/dart/sync/stream-data-define-asymmetric-object-description.rst new file mode 100644 index 0000000000..55c7631b4d --- /dev/null +++ b/source/includes/api-details/dart/sync/stream-data-define-asymmetric-object-description.rst @@ -0,0 +1,5 @@ +To define an asymmetric object, pass ``ObjectType.asymmetricObject`` to +``@RealmModel()``. + +For more information on how to define an asymmetric object, refer to +:ref:`sdks-asymmetric-objects`. diff --git a/source/includes/api-details/generic/sync/stream-data-create-asymmetric-objects-js-ts-description.rst b/source/includes/api-details/generic/sync/stream-data-create-asymmetric-objects-js-ts-description.rst new file mode 100644 index 0000000000..9aa0d8ff5a --- /dev/null +++ b/source/includes/api-details/generic/sync/stream-data-create-asymmetric-objects-js-ts-description.rst @@ -0,0 +1,4 @@ +Once you have an open database, you can create an asymmetric object inside +a write transaction using :js-sdk:`Realm.create() `. +When creating an asymmetric object, ``Realm.create()`` returns +``undefined`` rather than the object itself. diff --git a/source/includes/api-details/generic/sync/stream-data-define-asymmetric-object-js-ts-description.rst b/source/includes/api-details/generic/sync/stream-data-define-asymmetric-object-js-ts-description.rst new file mode 100644 index 0000000000..423ca25be2 --- /dev/null +++ b/source/includes/api-details/generic/sync/stream-data-define-asymmetric-object-js-ts-description.rst @@ -0,0 +1,7 @@ +Asymmetric objects sync data unidirectionally. Define an asymmetric object +by setting ``asymmetric`` to ``true`` in your object schema. For more +information, refer to the :js-sdk:`BaseObjectSchema API reference +`. + +For more information on how to define an asymmetric object, refer to +:ref:`Define an Asymmetric Object `. diff --git a/source/includes/api-details/kotlin/sync/stream-data-create-asymmetric-objects-description.rst b/source/includes/api-details/kotlin/sync/stream-data-create-asymmetric-objects-description.rst new file mode 100644 index 0000000000..c1f601102e --- /dev/null +++ b/source/includes/api-details/kotlin/sync/stream-data-create-asymmetric-objects-description.rst @@ -0,0 +1,3 @@ +Once you have an open database, you can create an ``AsymmetricRealmObject`` +inside a write transaction using the :kotlin-sync-sdk:`insert() ` +extension method: diff --git a/source/includes/api-details/kotlin/sync/stream-data-define-asymmetric-object-description.rst b/source/includes/api-details/kotlin/sync/stream-data-define-asymmetric-object-description.rst new file mode 100644 index 0000000000..00a116d595 --- /dev/null +++ b/source/includes/api-details/kotlin/sync/stream-data-define-asymmetric-object-description.rst @@ -0,0 +1,8 @@ +You can sync data unidirectionally when that object is an +``AsymmetricRealmObject``. + +Define an asymmetric object by implementing the +:kotlin-sync-sdk:`AsymmetricRealmObject ` +interface. + +.. include:: /includes/kotlin-asymmetric-object.rst diff --git a/source/includes/api-details/kotlin/sync/stream-data-open-synced-database-description.rst b/source/includes/api-details/kotlin/sync/stream-data-open-synced-database-description.rst new file mode 100644 index 0000000000..45323ed75d --- /dev/null +++ b/source/includes/api-details/kotlin/sync/stream-data-open-synced-database-description.rst @@ -0,0 +1,4 @@ +Specify the ``AsymmetricRealmObject`` types you want to sync. + +If you have non-asymmetric objects in the same database, you can add a +Sync subscription query for only those objects. diff --git a/source/includes/api-details/swift/sync/stream-data-create-asymmetric-objects-description.rst b/source/includes/api-details/swift/sync/stream-data-create-asymmetric-objects-description.rst new file mode 100644 index 0000000000..3e687160a9 --- /dev/null +++ b/source/includes/api-details/swift/sync/stream-data-create-asymmetric-objects-description.rst @@ -0,0 +1,3 @@ +Once you have an open database, you can create an ``AsymmetricObject`` inside +a write transaction using :swift-sdk:`create(_ type:, value:) +`. diff --git a/source/includes/api-details/swift/sync/stream-data-define-asymmetric-object-description.rst b/source/includes/api-details/swift/sync/stream-data-define-asymmetric-object-description.rst new file mode 100644 index 0000000000..db02cbb3f5 --- /dev/null +++ b/source/includes/api-details/swift/sync/stream-data-define-asymmetric-object-description.rst @@ -0,0 +1,6 @@ +You can sync data unidirectionally when that object is an ``AsymmetricObject``. +Define an AsymmetricObject by deriving from :swift-sdk:`AsymmetricObject +`. + +For more information on how to define an ``AsymmetricObject``, refer to +:ref:`Define an AsymmetricObject `. diff --git a/source/includes/api-details/swift/sync/stream-data-open-synced-database-description.rst b/source/includes/api-details/swift/sync/stream-data-open-synced-database-description.rst new file mode 100644 index 0000000000..82a38be092 --- /dev/null +++ b/source/includes/api-details/swift/sync/stream-data-open-synced-database-description.rst @@ -0,0 +1,14 @@ +Specify the ``AsymmetricObject`` types you want to sync. + +.. note:: Mixed Synced and Non-Synced Databases in Projects + + The ``AsymmetricObject`` type is incompatible with non-synced databases. + If your project uses both a synced and non-synced database, you must + explicitly :ref:`pass a subset of classes in your database configuration + ` to exclude the + ``AsymmetricObject`` from your non-synced database. + + Automatic schema discovery means that opening a non-synced database + without specifically excluding the ``AsymmetricObject`` from the + configuration can throw an error related to trying to use an + incompatible object type. diff --git a/source/includes/data-ingest-overview.rst b/source/includes/data-ingest-overview.rst deleted file mode 100644 index a780af058f..0000000000 --- a/source/includes/data-ingest-overview.rst +++ /dev/null @@ -1,12 +0,0 @@ -You can use :ref:`Data Ingest ` to stream -data from the client application to a Flexible Sync-enabled Atlas App Services -App. - -You might want to sync data unidirectionally in IoT applications, such as -a weather sensor sending data to the cloud. Data Ingest is also useful -for writing other types of immutable data where you do not require conflict -resolution, such as creating invoices from a retail app or logging application -events. - -Data Ingest is optimized to provide performance improvements for heavy -client-side *insert-only* workloads. \ No newline at end of file diff --git a/source/includes/dotnet-asymmetric-object.rst b/source/includes/dotnet-asymmetric-object.rst new file mode 100644 index 0000000000..9ca6bc1372 --- /dev/null +++ b/source/includes/dotnet-asymmetric-object.rst @@ -0,0 +1,18 @@ +When defining an asymmetric object in C#: + +- The C# objects that you sync with Atlas must implement the + :dotnet-sdk:`IAsymmetricObject ` + interface or derive from the + :dotnet-sdk:`AsymmetricObject ` class. + +- Starting in .NET SDK version 11.6.0 and later, an object that implements + ``IAsymmetricObject`` can contain + :dotnet-sdk:`IEmbeddedObject ` types, + and links to ``IRealmObject`` types. In .NET SDK versions 11.5.0 and earlier, + an object that implements ``IAsymmetricObject`` can only contain + :dotnet-sdk:`IEmbeddedObject ` types - + it does not support links to ``IRealmObject`` types or other + ``IAsymmetricObject`` types. + +- ``IRealmObject`` and ``IEmbeddedObject`` types cannot contain ``IAsymmetricObject`` + types as properties. diff --git a/source/includes/kotlin-asymmetric-object.rst b/source/includes/kotlin-asymmetric-object.rst index ec057c67a4..8b0bfea0ba 100644 --- a/source/includes/kotlin-asymmetric-object.rst +++ b/source/includes/kotlin-asymmetric-object.rst @@ -1,17 +1,16 @@ Asymmetric objects broadly support the same property types as ``RealmObject``, with a few exceptions: -- Asymmetric objects can only be used in synced realms configured with - Flexible Sync. However, you cannot create subscriptions to - asymmetric objects. +- Asymmetric objects can only be used in synced databases. However, you cannot + create subscriptions to asymmetric objects. - An ``AsymmetricRealmObject`` can contain ``EmbeddedRealmObject`` types, but *cannot* contain ``RealmObject`` types or other ``AsymmetricRealmObject`` types. - ``AsymmetricRealmObject`` types *cannot* be used as properties in other - Realm objects. + database objects. -Additionally, asymmetric objects do not function in the same way as other Realm objects. -You cannot add, read, update, or delete an asymmetric object from the realm. -You can only create an asymmetric object, which then syncs unidirectionally -to the Atlas database linked to your App with Device Sync. -Realm then deletes this object after syncing. \ No newline at end of file +Additionally, asymmetric objects do not function in the same way as other +database objects. You cannot add, read, update, or delete an asymmetric object +from the database. You can only create an asymmetric object, which then syncs +unidirectionally to the Atlas database linked to your App with Device Sync. +The SDK then deletes this object after syncing. diff --git a/source/includes/sdk-examples/sync/stream-data-connect-and-authenticate.rst b/source/includes/sdk-examples/sync/stream-data-connect-and-authenticate.rst new file mode 100644 index 0000000000..507daa901f --- /dev/null +++ b/source/includes/sdk-examples/sync/stream-data-connect-and-authenticate.rst @@ -0,0 +1,47 @@ +.. tabs-drivers:: + + tabs: + - id: cpp-sdk + content: | + + .. literalinclude:: /examples/generated/cpp/asymmetric-sync.snippet.connect-and-authenticate.cpp + :language: cpp + + - id: csharp + content: | + + .. literalinclude:: /examples/generated/dotnet/Asymmetrics.snippet.connect-and-authenticate.cs + :language: csharp + + - id: dart + content: | + + .. literalinclude:: /examples/generated/flutter/app_services_test.snippet.access-app-client.dart + :language: dart + + .. literalinclude:: /examples/generated/flutter/authenticate_users_test.snippet.anonymous-credentials.dart + :language: dart + + - id: javascript + content: | + + .. literalinclude:: /examples/generated/node/authenticate.snippet.anonymous-login.js + :language: javascript + + - id: kotlin + content: | + + .. literalinclude:: /examples/generated/kotlin/AsymmetricSyncTest.snippet.connect-and-authenticate.kt + :language: kotlin + + - id: swift + content: | + + .. literalinclude:: /examples/generated/code/start/AsymmetricSync.snippet.connect-and-authenticate.swift + :language: swift + + - id: typescript + content: | + + .. literalinclude:: /examples/generated/node/authenticate.snippet.anonymous-login.ts + :language: typescript diff --git a/source/includes/sdk-examples/sync/stream-data-create-asymmetric-objects.rst b/source/includes/sdk-examples/sync/stream-data-create-asymmetric-objects.rst new file mode 100644 index 0000000000..6f3acf26c1 --- /dev/null +++ b/source/includes/sdk-examples/sync/stream-data-create-asymmetric-objects.rst @@ -0,0 +1,44 @@ +.. tabs-drivers:: + + tabs: + - id: cpp-sdk + content: | + + .. literalinclude:: /examples/generated/cpp/asymmetric-sync.snippet.create-asymmetric-object.cpp + :language: cpp + + - id: csharp + content: | + + .. literalinclude:: /examples/generated/dotnet/Asymmetrics.snippet.asymmetry.cs + :language: csharp + + - id: dart + content: | + + .. literalinclude:: /examples/generated/flutter/data_ingest.test.snippet.write-asymmetric-object.dart + :language: dart + + - id: javascript + content: | + + .. literalinclude:: /examples/MissingPlaceholders/example.js + :language: javascript + + - id: kotlin + content: | + + .. literalinclude:: /examples/generated/kotlin/AsymmetricSyncTest.snippet.create-asymmetric-object.kt + :language: kotlin + + - id: swift + content: | + + .. literalinclude:: /examples/generated/code/start/AsymmetricSync.snippet.create-asymmetric-object.swift + :language: swift + + - id: typescript + content: | + + .. literalinclude:: /examples/generated/node/asymmetric-sync.snippet.write-asymmetric-object.ts + :language: typescript diff --git a/source/includes/sdk-examples/sync/stream-data-define-asymmetric-object.rst b/source/includes/sdk-examples/sync/stream-data-define-asymmetric-object.rst new file mode 100644 index 0000000000..b734aa62a8 --- /dev/null +++ b/source/includes/sdk-examples/sync/stream-data-define-asymmetric-object.rst @@ -0,0 +1,47 @@ +.. tabs-drivers:: + + tabs: + - id: cpp-sdk + content: | + + .. literalinclude:: /examples/generated/cpp/asymmetric-sync.snippet.asymmetric-object.cpp + :language: cpp + + - id: csharp + content: | + + .. literalinclude:: /examples/generated/dotnet/Asymmetrics.snippet.define-asymmetric-object.cs + :language: csharp + + - id: dart + content: | + + .. literalinclude:: /examples/generated/flutter/data_ingest.test.snippet.asymmetric-sync-object.dart + :language: dart + :emphasize-lines: 1 + + - id: javascript + content: | + + .. literalinclude:: /examples/generated/node/asymmetric-sync.snippet.asymmetric-sync-object.js + :language: javascript + :emphasize-lines: 6 + + - id: kotlin + content: | + + .. literalinclude:: /examples/generated/kotlin/Schema.snippet.define-asymmetric-model.kt + :language: kotlin + + - id: swift + content: | + + .. literalinclude:: /examples/generated/code/start/AsymmetricSync.snippet.asymmetric-model.swift + :language: swift + + - id: typescript + content: | + + .. literalinclude:: /examples/generated/node/asymmetric-sync.snippet.asymmetric-sync-object.ts + :language: typescript + :emphasize-lines: 12 diff --git a/source/includes/sdk-examples/sync/stream-data-open-synced-database.rst b/source/includes/sdk-examples/sync/stream-data-open-synced-database.rst new file mode 100644 index 0000000000..9418eb5aec --- /dev/null +++ b/source/includes/sdk-examples/sync/stream-data-open-synced-database.rst @@ -0,0 +1,44 @@ +.. tabs-drivers:: + + tabs: + - id: cpp-sdk + content: | + + .. literalinclude:: /examples/generated/cpp/asymmetric-sync.snippet.open-asymmetric-synced-realm.cpp + :language: cpp + + - id: csharp + content: | + + .. literalinclude:: /examples/generated/dotnet/Asymmetrics.snippet.configure-and-open-db.cs + :language: csharp + + - id: dart + content: | + + .. literalinclude:: /examples/generated/flutter/open_flexible_sync_realm_test.snippet.open-flexible-sync-realm.dart + :language: dart + + - id: javascript + content: | + + .. literalinclude:: /examples/MissingPlaceholders/example.js + :language: javascript + + - id: kotlin + content: | + + .. literalinclude:: /examples/generated/kotlin/AsymmetricSyncTest.snippet.open-asymmetric-sync-realm.kt + :language: kotlin + + - id: swift + content: | + + .. literalinclude:: /examples/generated/code/start/AsymmetricSync.snippet.open-asymmetric-sync-realm.swift + :language: swift + + - id: typescript + content: | + + .. literalinclude:: /examples/generated/node/asymmetric-sync.snippet.open-realm.ts + :language: typescript diff --git a/source/sdk/files/configure-and-open.txt b/source/sdk/files/configure-and-open.txt index 2d15768a84..47eaa2771a 100644 --- a/source/sdk/files/configure-and-open.txt +++ b/source/sdk/files/configure-and-open.txt @@ -30,3 +30,8 @@ schema). i.e. it's a collection of all the object schemas that the database file can manage. Some SDKs require explicit realm file schemas, while others automatically manage schemas for any object in your project, and you can specify a subset of schemas (objects) when opening a realm. + +.. _sdks-provide-a-subset-of-classes-to-a-database: + +Provide a Subset of Classes to a Database +----------------------------------------- diff --git a/source/sdk/sync/stream-data-to-atlas.txt b/source/sdk/sync/stream-data-to-atlas.txt index 8b59c16729..f7482927a6 100644 --- a/source/sdk/sync/stream-data-to-atlas.txt +++ b/source/sdk/sync/stream-data-to-atlas.txt @@ -4,10 +4,186 @@ Stream Data to Atlas ==================== +.. meta:: + :description: Stream data from your client device to Atlas for heavy insert-only workloads using Data Ingest. + :keywords: Realm, C++ SDK, Flutter SDK, Kotlin SDK, Node.js SDK, Swift SDK, code example + +.. facet:: + :name: genre + :values: tutorial + +.. facet:: + :name: programming_language + :values: cpp, csharp, dart, javascript/typescript, kotlin, swift + .. contents:: On this page :local: :backlinks: none :depth: 2 :class: singlecol -Placeholder page for information about asymmetric sync/data ingest. +.. tabs-selector:: drivers + +If you have a mobile or client application that produces a large volume of data +you'd like to stream to MongoDB Atlas, you can sync data unidirectionally using +Device Sync. We call the feature that enables this unidirectional sync **Data Ingest**. + +You can use :ref:`Data Ingest ` to stream +data from the client application to a Device Sync-enabled Atlas App Services +App. + +You might want to sync data unidirectionally in IoT applications, such as +a weather sensor sending data to the cloud. Data Ingest is also useful +for writing other types of immutable data where you do not require conflict +resolution, such as creating invoices from a retail app or logging application +events. + +Data Ingest is optimized to provide performance improvements for heavy +client-side *insert-only* workloads. + +.. _sdks-data-ingest-procedure: + +Sync Data Unidirectionally from a Client Application +---------------------------------------------------- + +To use Data Ingest, stream data to Atlas using insert-only +**asymmetric objects** in a synced database. + +Atlas Device Sync completely manages the lifecycle of this data. The SDK +maintains it on the device until Data Ingest synchronization is complete. Then, +the SDK removes the data from the device. + +You cannot read, query, or delete an asymmetric object from a database. +Asymmetric objects are incompatible with standard, bi-directional Device Sync +or a non-synced database. + +.. procedure:: + + .. step:: Define an Asymmetric Object + + .. tabs-drivers:: + + .. tab:: + :tabid: cpp-sdk + + .. include:: /includes/api-details/cpp/sync/stream-data-define-asymmetric-object-description.rst + + .. tab:: + :tabid: csharp + + .. include:: /includes/api-details/csharp/sync/stream-data-define-asymmetric-object-description.rst + + .. tab:: + :tabid: dart + + .. include:: /includes/api-details/dart/sync/stream-data-define-asymmetric-object-description.rst + + .. tab:: + :tabid: javascript + + .. include:: /includes/api-details/generic/sync/stream-data-define-asymmetric-object-js-ts-description.rst + + .. tab:: + :tabid: kotlin + + .. include:: /includes/api-details/kotlin/sync/stream-data-define-asymmetric-object-description.rst + + .. tab:: + :tabid: swift + + .. include:: /includes/api-details/swift/sync/stream-data-define-asymmetric-object-description.rst + + .. tab:: + :tabid: typescript + + .. include:: /includes/api-details/generic/sync/stream-data-define-asymmetric-object-js-ts-description.rst + + .. include:: /includes/sdk-examples/sync/stream-data-define-asymmetric-object.rst + + .. step:: Connect and Authenticate with an App Services App + + To stream data from the client to your backend App, you must + :ref:`connect to Atlas ` and + :ref:`authenticate a user `. + + .. include:: /includes/sdk-examples/sync/stream-data-connect-and-authenticate.rst + + .. step:: Open a Synced Database + + After you have an authenticated user, open a :ref:`synced database + `. + + Unlike bi-directional Device Sync, Data Ingest does not use a + :ref:`Sync subscription `. + + .. tabs-drivers:: + + .. tab:: + :tabid: cpp-sdk + + .. include:: /includes/api-details/cpp/sync/stream-data-open-database-description.rst + + .. tab:: + :tabid: csharp + + .. tab:: + :tabid: dart + + .. tab:: + :tabid: javascript + + .. tab:: + :tabid: kotlin + + .. include:: /includes/api-details/kotlin/sync/stream-data-open-synced-database-description.rst + + .. tab:: + :tabid: swift + + .. include:: /includes/api-details/swift/sync/stream-data-open-synced-database-description.rst + + .. tab:: + :tabid: typescript + + .. include:: /includes/sdk-examples/sync/stream-data-open-synced-database.rst + + .. step:: Create Asymmetric Objects + + .. tabs-drivers:: + + .. tab:: + :tabid: cpp-sdk + + .. include:: /includes/api-details/cpp/sync/stream-data-create-asymmetric-objects-description.rst + + .. tab:: + :tabid: csharp + + .. include:: /includes/api-details/csharp/sync/stream-data-create-asymmetric-objects-description.rst + + .. tab:: + :tabid: dart + + .. include:: /includes/api-details/dart/sync/stream-data-create-asymmetric-objects-description.rst + + .. tab:: + :tabid: javascript + + .. include:: /includes/api-details/generic/sync/stream-data-create-asymmetric-objects-js-ts-description.rst + + .. tab:: + :tabid: kotlin + + .. include:: /includes/api-details/kotlin/sync/stream-data-create-asymmetric-objects-description.rst + + .. tab:: + :tabid: swift + + .. include:: /includes/api-details/swift/sync/stream-data-create-asymmetric-objects-description.rst + + .. tab:: + :tabid: typescript + + .. include:: /includes/api-details/generic/sync/stream-data-create-asymmetric-objects-js-ts-description.rst + + .. include:: /includes/sdk-examples/sync/stream-data-create-asymmetric-objects.rst diff --git a/temp/cpp/sync/stream-data-to-atlas.txt b/temp/cpp/sync/stream-data-to-atlas.txt index 0788cd2f6c..7cc6528cfb 100644 --- a/temp/cpp/sync/stream-data-to-atlas.txt +++ b/temp/cpp/sync/stream-data-to-atlas.txt @@ -29,12 +29,12 @@ Sync Data Unidirectionally from a Client Application You can sync data unidirectionally when you declare an object's schema as a ``REALM_ASYMMETRIC_SCHEMA``. - .. literalinclude:: /examples/generated/cpp/asymmetric-sync.snippet.asymmetric-object.cpp - :language: cpp - For more information on how to define a ``REALM_ASYMMETRIC_SCHEMA``, including limitations when linking to other object types, see: :ref:`Define an Asymmetric Object `. + + .. literalinclude:: /examples/generated/cpp/asymmetric-sync.snippet.asymmetric-object.cpp + :language: cpp .. step:: Connect and Authenticate with an App Services App diff --git a/temp/dotnet/app-services/connect-to-app-services-backend.txt b/temp/dotnet/app-services/connect-to-app-services-backend.txt index 4350121060..12d0cfc9ea 100644 --- a/temp/dotnet/app-services/connect-to-app-services-backend.txt +++ b/temp/dotnet/app-services/connect-to-app-services-backend.txt @@ -48,6 +48,62 @@ You can create multiple App client instances to connect to multiple Apps. All App client instances that share the same App ID use the same underlying connection. +.. _dotnet-connect-to-specific-server: + +Connect to a Specific Server +---------------------------- + +By default, Atlas Device SDK connects to Atlas using the global ``baseURL`` +of ``https://services.cloud.mongodb.com``. In some cases, you may want to +connect to a different server: + +- Your App Services App uses :ref:`local deployment `, and + you want to connect directly to a local ``baseURL`` in your region. +- You want to connect to an :ref:`Edge Server instance `. + +You can specify a ``baseURL`` in the +:dotnet-sdk:`AppConfiguration `. + +.. literalinclude:: /examples/generated/dotnet/BaseURLChange.snippet.custom-base-url.cs + :language: csharp + +Connect to a Different Server During Runtime +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 12.1.0 + +In some cases, you might want to change the ``baseURL`` while the app is +running. For example, you might want to roam between Edge Servers, or +move from an App Services connection to an Edge Server connection. To change +the ``baseURL`` during runtime, call the +:dotnet-sdk:`app.UpdateBaseUriAsync() ` +method: + +.. literalinclude:: /examples/generated/dotnet/BaseURLChange.snippet.update-base-url.cs + :language: csharp + +This API is experimental. As seen above, you must use ``#pragma warning disable Rlm001`` +and ``#pragma warning restore Rlm001`` to suppress the experimental errors, +where ``Rlm001`` is the experimental attributes's ``diagnosticId``. You must +also import the following namespace at the top of your file, which contains +the ``Experimental`` attribute: + +.. literalinclude:: /examples/generated/dotnet/BaseURLChange.snippet.experimental-import.cs + :language: csharp + +If you want to change the ``baseURL`` after you have logged in a user and +have opened a synced database, the app must perform a +:ref:`client reset `. Perform these steps in your code: + +1. :ref:`Pause the Sync session `. +2. Update the ``baseURL`` by calling the ``app.updateBaseUrl(to: )`` method. +3. Authenticate and log the user in again with the new ``baseURL``. +4. Open a synced database pulling data from the new server. + +Both the server and the client must be online for the user to authenticate and +connect to the new server. If the server is not online or the client does not +have a network connection, the user cannot authenticate and open the database. + .. important:: Changing an App Config After Initializing the App .. versionchanged:: v11.7.0 diff --git a/temp/flutter/sync/stream-data-to-atlas.txt b/temp/flutter/sync/stream-data-to-atlas.txt index 53f021ad09..512693bd7f 100644 --- a/temp/flutter/sync/stream-data-to-atlas.txt +++ b/temp/flutter/sync/stream-data-to-atlas.txt @@ -23,13 +23,13 @@ Sync Data Unidirectionally from a Client Application asymmetric object, pass ``ObjectType.asymmetricObject`` to ``@RealmModel()``. + For more information on how to define an asymmetric object, refer to + :ref:`Define an Asymmetric Object `. + .. literalinclude:: /examples/generated/flutter/data_ingest.test.snippet.asymmetric-sync-object.dart :language: dart :emphasize-lines: 1 - For more information on how to define an asymmetric object, refer to - :ref:`Define an Asymmetric Object `. - .. step:: Connect and Authenticate with an App Services App To stream data from the client to your backend App, you must @@ -63,7 +63,7 @@ Sync Data Unidirectionally from a Client Application a write transaction. Pass your object data to ``realm.ingest``. .. literalinclude:: /examples/generated/flutter/data_ingest.test.snippet.write-asymmetric-object.dart - :language: dart + :language: dart You can't read asymmetric objects. Once created, they sync to the App Services backend and the linked Atlas database. diff --git a/temp/node/sync/stream-data-to-atlas.txt b/temp/node/sync/stream-data-to-atlas.txt index d72417534b..7949cb5a9e 100644 --- a/temp/node/sync/stream-data-to-atlas.txt +++ b/temp/node/sync/stream-data-to-atlas.txt @@ -21,7 +21,10 @@ Sync Data Unidirectionally from a Client Application Asymmetric objects sync data unidirectionally. Define an asymmetric object by setting ``asymmetric`` to ``true`` in your :js-sdk:`object model - `: + `. + + For more information on how to define an asymmetric object, refer to + :ref:`Define an Asymmetric Object `. .. tabs-realm-languages:: @@ -39,9 +42,6 @@ Sync Data Unidirectionally from a Client Application :language: javascript :emphasize-lines: 6 - For more information on how to define an asymmetric object, refer to - :ref:`Define an Asymmetric Object `. - .. step:: Connect and Authenticate with an App Services App To stream data from the client to your backend App, you must diff --git a/temp/swift/sync/stream-data-to-atlas.txt b/temp/swift/sync/stream-data-to-atlas.txt index bf144504ec..a9c789a73c 100644 --- a/temp/swift/sync/stream-data-to-atlas.txt +++ b/temp/swift/sync/stream-data-to-atlas.txt @@ -26,14 +26,14 @@ Sync Data Unidirectionally from a Client Application You can sync data unidirectionally when that object is an ``AsymmetricObject``. Define an AsymmetricObject by deriving from :swift-sdk:`AsymmetricObject - `: - - .. literalinclude:: /examples/generated/code/start/AsymmetricSync.snippet.asymmetric-model.swift - :language: swift + `. For more information on how to define an ``AsymmetricObject``, see: :ref:`Define an AsymmetricObject `. + .. literalinclude:: /examples/generated/code/start/AsymmetricSync.snippet.asymmetric-model.swift + :language: swift + .. step:: Connect and Authenticate with an App Services App To stream data from the client to your backend App, you must