-
Notifications
You must be signed in to change notification settings - Fork 88
Open a Realm, Call a Function #519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a couple of small nits.
examples/dotnet/Examples/Examples.cs
Outdated
var result = await | ||
user.Functions.CallAsync("sum", 2, 40); | ||
|
||
// result.ToInt32() == 42 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, this comment looks a little out of place in the code-snippet on this page. Could we maybe store the result in a variable and print it out instead?
source/dotnet/open-a-realm.txt
Outdated
|
||
Open a Local (Non-Synced) Realm | ||
------------------------------- | ||
When opening a local (non-synced) {+realm+}, you pass a ``RealmConfiguration`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When opening a local (non-synced) {+realm+}, you pass a ``RealmConfiguration`` | |
When opening a local (non-synced) {+realm+}, pass a ``RealmConfiguration`` |
extraneous word, I would probably just trim this.
source/dotnet/open-a-realm.txt
Outdated
Close a Realm | ||
------------- | ||
There is no need to manually close a {+realm+} with the .NET SDK. When a {+realm+} | ||
goes out of scope and is removed from memory, the {+realm+} is closed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great. I wish the other SDKs did this 😢
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not true unfortunately. The Realm
instance implements IDisposable
(see https://realm.io/docs/dotnet/latest/#closing-realm-instances) so the general recommendation is to open a Realm instance with a using
, unless that instance is going to be long lived (e.g. on the main thread) and you need to continuously read/write data to it as the user interacts with the app. It's true that we have hooks into GC to do that for you, but the issue is that the majority of the memory associated with a Realm instance is native memory which GC doesn't know about. This means that it may take a long time between an instance going out of scope and it being collected because the GC sees it as a very lightweight object and may decide not to run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a few small corrections, but looks good overall.
source/dotnet/open-a-realm.txt
Outdated
|
||
In the above example, the code shows how to open the {+realm+} *asynchronously* | ||
by calling ``GetInstanceAsync``. You can also open a {+realm+} *synchronously* | ||
by calling ``GetInstance``, but this may lead to temporary data inconsistencies |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that's very clear - there are no data inconsistencies associated with opening a Realm file synchronously and I don't believe we have strong recommendations against it. In fact, opening a Realm asynchronously is only possible if the device is online and it kind of defeats one of the major selling points for Realm.
I believe the general recommendation we have is to use GetInstanceAsync
the first time a user logs in as it's likely that they're connected at this point, but switch to GetInstance
after that to ensure offline capabilities.
examples/dotnet/Examples/Examples.cs
Outdated
user = app.LogInAsync(Credentials.EmailPassword("[email protected]", "foobar")).Result; | ||
// :code-block-start: open-synced-realm | ||
config = new SyncConfiguration("My Project", user); | ||
Realm realm = await Realm.GetInstanceAsync(config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
source/dotnet/open-a-realm.txt
Outdated
|
||
.. note:: | ||
|
||
If you specify a local path, that path must already exist on the device. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only the case when opening the realm with IsReadOnly = true
, which is probably fairly rare. If you're opening a Realm in a read/write mode, the SDK will create the file if it didn't exist before that.
source/dotnet/open-a-realm.txt
Outdated
Close a Realm | ||
------------- | ||
There is no need to manually close a {+realm+} with the .NET SDK. When a {+realm+} | ||
goes out of scope and is removed from memory, the {+realm+} is closed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not true unfortunately. The Realm
instance implements IDisposable
(see https://realm.io/docs/dotnet/latest/#closing-realm-instances) so the general recommendation is to open a Realm instance with a using
, unless that instance is going to be long lived (e.g. on the main thread) and you need to continuously read/write data to it as the user interacts with the app. It's true that we have hooks into GC to do that for you, but the issue is that the majority of the memory associated with a Realm instance is native memory which GC doesn't know about. This means that it may take a long time between an instance going out of scope and it being collected because the GC sees it as a very lightweight object and may decide not to run.
{ | ||
// :code-block-start: callfunc | ||
var result = await | ||
user.Functions.CallAsync("sum", 2, 40); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably a good idea to showcase the generic overload of CallAsync
so that we don't have to work with the raw BsonValue. I believe this would look like var result = await user.Function.CallAsync<int>("sum", 2, 40);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Final nits and clarifications! Thanks for bearing with me and my obsessiveness 🙏
conf.py
Outdated
@@ -109,6 +109,7 @@ | |||
'swift-sdk': ('https://docs.mongodb.com/realm-sdks/swift/10.0.0-rc.1/%s', ''), | |||
'objc-sdk': ('https://docs.mongodb.com/realm-sdks/objc/10.0.0-rc.1/%s', ''), | |||
'js-sdk': ('https://docs.mongodb.com/realm-sdks/js/latest/%s', ''), | |||
'dotnet-sdk': ('https://docs.mongodb.com/realm-sdks/js/latest/%s', ''), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be updated to .../dotnet/latest/...
?
examples/dotnet/Examples/Examples.cs
Outdated
{ | ||
Name = "Do this thing", | ||
Status = TaskStatus.Open.ToString() | ||
Status = dotnet.TaskStatus.Open.ToString() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably don't want to use the namespace here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it conflicts with something, you can add
using TaskStatus = dotnet.TaskStatus;
next to your using statements to help the compiler resolve the correct type.
examples/dotnet/Examples/Examples.cs
Outdated
{ | ||
// :code-block-start: scope | ||
config = new SyncConfiguration("My Project", user); | ||
using (var realm = await Realm.GetInstanceAsync(config)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can showcase the new using
syntax from C# 8 here and simplify the code a little:
config = new SyncConfiguration(...);
using var realm = await Realm.GetInstanceAsync(...);
var allTasks = realm.All<RealmTask>();
source/dotnet/call-a-function.txt
Outdated
|
||
.. note:: | ||
The ``CallAsync()`` method returns a raw ``BsonValue``, which must be cast to the | ||
expected type, unless you use one of the generic overloads. In the example above, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[super-nit] There's only one generic overload for CallAsync
.
|
||
.. note:: | ||
|
||
The first time a user logs on to your realm app, you should open the realm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use a less compelling verb - i.e. The first time a user logs on to your realm app, it is recommended to open the realm *asynchronously*
.
And on a separate note - before the acquisition, the branding instructions stated that we should capitalize Realm when talking about the files - e.g. "Can you send me your Realm file", "To open a synchronized Realm, just pass in a SyncConfiguration with a logged in user", etc. Not sure if that has changed, but might want to sync up with the docs/marketing teams to ensure we're consistent in the usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I hadn't seen this, but super helpful - I just need to untrain my brain to uppercase the local file 😅 But I guess the realm
in your realm app
needs to be uppercase then?
source/dotnet/open-a-realm.txt
Outdated
|
||
Scoping the Realm | ||
----------------- | ||
The Realm instance implements ``IDisposable``, and you should dispose of a realm |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would reword this slightly to make it less forceful:
The Realm class implements ``IDisposable`` to clean up the native resources it uses. It is recommended
to always dispose of Realm instances after use, especially on background threads. The simplest way is to
declare the variable with a `using` or wrap the code that interacts with a Realm in a `using (...)` statement:
Also, might be worth adding a note that disposing of a Realm instance will invalidate all objects associated with that instance, so if the developer needs to use them throughout the lifetime of the app - e.g. for databinding purposes on the main thread - it's safe not to dispose of the Realm. The rule of thumb is "don't dispose on the main thread, dispose on background ones".
Pull Request Info
Issue JIRA links:
Open a Realm: https://jira.mongodb.org/browse/DOCSP-12487
Call a Function: https://jira.mongodb.org/browse/DOCSP-12476
Docs staging link (requires sign-in on MongoDB Corp SSO):
OaR: https://docs-mongodbcom-staging.corp.mongodb.com/realm/caleb/clientguide/dotnet/open-a-realm.html
CaF: https://docs-mongodbcom-staging.corp.mongodb.com/realm/caleb/clientguide/dotnet/call-a-function.html