Reputation: 1
I’m using this MongoDB template, which works well for uploading Item objects to MongoDB Cloud. However, I want to upload a new object type, UserRecord. Here's the class definition:
using MongoDB.Bson;
using Realms;
using RealmTodo.Services;
namespace RealmTodo.Models
{
public partial class UserRecord : IRealmObject
{
[PrimaryKey]
[MapTo("_id")]
public ObjectId Id { get; set; } = ObjectId.GenerateNewId();
[MapTo("owner_id")]
[Required]
public string OwnerId { get; set; }
[MapTo("summary")]
[Required]
public string Summary { get; set; }
[MapTo("mapName")]
public string MapName { get; set; }
[MapTo("trackTime")]
public string TrackTime { get; set; }
[MapTo("uploadDate")]
public string UploadDate { get; set; }
public bool IsMine => OwnerId == RealmService.CurrentUser.Id;
}
}
Below is the RealmService code I’m using:
using System.Text.Json;
using Realms;
using Realms.Sync;
using RealmTodo.Models;
namespace RealmTodo.Services
{
public static class RealmService
{
private static bool serviceInitialised;
private static Realms.Sync.App app;
private static Realm mainThreadRealm;
public static User CurrentUser => app.CurrentUser;
public static string DataExplorerLink;
public static async Task Init()
{
if (serviceInitialised)
{
return;
}
using Stream fileStream = await FileSystem.Current.OpenAppPackageFileAsync("atlasConfig.json");
using StreamReader reader = new(fileStream);
var fileContent = await reader.ReadToEndAsync();
var config = JsonSerializer.Deserialize<RealmAppConfig>(fileContent,
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var appConfiguration = new AppConfiguration(config.AppId)
{
BaseUri = new Uri(config.BaseUrl)
};
app = Realms.Sync.App.Create(appConfiguration);
serviceInitialised = true;
// If you're getting this app code by cloning the repository at
// https://github.com/mongodb/template-app-maui-todo,
// it does not contain the data explorer link. Download the
// app template from the Atlas UI to view a link to your data.
DataExplorerLink = config.DataExplorerLink;
Console.WriteLine($"To view your data in Atlas, use this link: {DataExplorerLink}");
}
public static Realm GetMainThreadRealm()
{
return mainThreadRealm ??= GetRealm();
}
public static Realm GetRealm()
{
var config = new FlexibleSyncConfiguration(app.CurrentUser)
{
PopulateInitialSubscriptions = (realm) =>
{
var (query, queryName) = GetQueryForSubscriptionType(realm, SubscriptionType.Mine);
realm.Subscriptions.Add(query, new SubscriptionOptions { Name = queryName });
}
};
return Realm.GetInstance(config);
}
public static async Task RegisterAsync(string email, string password)
{
await app.EmailPasswordAuth.RegisterUserAsync(email, password);
}
public static async Task LoginAsync(string email, string password)
{
await app.LogInAsync(Credentials.EmailPassword(email, password));
//This will populate the initial set of subscriptions the first time the realm is opened
using var realm = GetRealm();
await realm.Subscriptions.WaitForSynchronizationAsync();
}
public static async Task LogoutAsync()
{
await app.CurrentUser.LogOutAsync();
mainThreadRealm?.Dispose();
mainThreadRealm = null;
}
public static async Task SetSubscription(Realm realm, SubscriptionType subType)
{
if (GetCurrentSubscriptionType(realm) == subType)
{
return;
}
realm.Subscriptions.Update(() =>
{
realm.Subscriptions.RemoveAll(true);
var (query, queryName) = GetQueryForSubscriptionType(realm, subType);
realm.Subscriptions.Add(query, new SubscriptionOptions { Name = queryName });
});
//There is no need to wait for synchronization if we are disconnected
if (realm.SyncSession.ConnectionState != ConnectionState.Disconnected)
{
await realm.Subscriptions.WaitForSynchronizationAsync();
}
}
public static SubscriptionType GetCurrentSubscriptionType(Realm realm)
{
var activeSubscription = realm.Subscriptions.FirstOrDefault();
return activeSubscription.Name switch
{
"all" => SubscriptionType.All,
"mine" => SubscriptionType.Mine,
_ => throw new InvalidOperationException("Unknown subscription type")
};
}
private static (IQueryable<UserRecord> Query, string Name) GetQueryForSubscriptionType(Realm realm, SubscriptionType subType)
{
IQueryable<UserRecord> query = null;
string queryName = null;
if (subType == SubscriptionType.Mine)
{
query = realm.All<UserRecord>().Where(i => i.OwnerId == CurrentUser.Id);
queryName = "mine";
}
else if (subType == SubscriptionType.All)
{
query = realm.All<UserRecord>();
queryName = "all";
}
else
{
throw new ArgumentException("Unknown subscription type");
}
return (query, queryName);
}
}
public enum SubscriptionType
{
Mine,
All,
}
public class RealmAppConfig
{
public string AppId { get; set; }
public string BaseUrl { get; set; }
// If you're getting this app code by cloning the repository at
// https://github.com/mongodb/template-app-maui-todo,
// it does not contain the data explorer link. Download the
// app template from the Atlas UI to view a link to your data.
public string DataExplorerLink { get; set; }
}
}
Issue When I attempt to upload a UserRecord object, I get this error: Realms.Exceptions.RealmException: 'Cannot write to class UserRecord when no flexible sync subscription has been created.' What I’ve Tried I ensured that Device Sync was properly configured through the MongoDB UI.
The sync model screen in MongoDB Cloud does recognize the UserRecord object.
Here's a screenshot of the sync models:
enter image description here
My Project Repository Here is the link to my repository based on the original MongoDB template: https://github.com/t4tomer/RealmTimerExample
What I Expected I expected UserRecord objects to sync with MongoDB Cloud, just like the Item objects in the template app.
Question: How can I resolve this error and successfully sync UserRecord objects with MongoDB Cloud? Am I missing any additional steps for configuring flexible sync?
here is the Field Permissionsfor UserRecord object : enter image description here
Pic of the error : enter image description here
Upvotes: 0
Views: 65