I'm considering switching from SQLite to Realm in my UWP applications, as Realm seems fairly easier to setup, but I'm having trouble with some limitations that so far are a deal-breaker for me, the most important one being that apparently you can't use realm objects after disposing the Realm
instance that was used to retrieve them. So I wonder how am I supposed to load data to throw in a ViewModel, as after loading the data items that Realm
instance would be gone.
Here's an example of a really basic ViewModel:
public class MyViewModel : ViewModelBase // Assume this has INotifyPropertyChanged setup
{
private IEnumerable<MyItem> _Items;
public IEnumerable<MyItem> Items
{
get => _Items;
private set => Set(nameof(Items), ref _Items, value);
}
public async Task LoadDataAsync()
{
using (Realm realm = await Realm.GetInstanceAsync())
{
Items = realm.All<MyItem>().ToArray();
}
}
}
Assume that MyItem
is some example model, which inherits from RealmObject
.
Now, if I were using SQLite, I'd have no problems whatsoever there, as once retrieved from the database, each model instance would be a standalone object that I could just store in my ViewModel. Instead, classes that inherit from RealObject
are linked to their original Realm
instance, so if I try to use them (ie. read one of their properties) after the source Realm
instance has been disposed, everything falls apart (I get a nice Exception
).
The obvious workaround would be to keep two classes for each model: one that maps to the Realm database, and another one that's a standalone object. But this has some drawbacks:
- Twice the number of classes
- Additional work (and memory waste) to copy each instance to the standalone class
- This just seems wrong, I mean, come on
Another possibility would be to keep a singleton instance of a Realm
object that is never closed, but doesn't sound like a good idea either (and it would have problems when using multiple threads too, so it's definitely not a valid solution).
I've seen that the Java version of the Realm library has some "getRawObject" method (or something like that) that allows you to get a standalone copy of a RealmObject
, but still, I guess this actually creates a copy of the model instance, so it doesn't sound good either.
My question is:
Is there a way to just get the same flexibility of SQLite, where once loaded, you can pass the models around anywhere you want (including to other threads), use them in ViewModels, and then also eventually edit them and pass them back around to the database to update them on disk?
Bonus point: as another example, consider a library that loads some items from a Realm database and return them to the user. Once loaded, those objects would be read-only, meaning that even if they somehow were modified, they wouldn't be changed on the database itself. My current solution is again to copy each loaded model into another classes that doesn't inherit from RealmObject
, but as I said, this is not scalable at all (imagine a large project with dozens of models, it would be impossible to do so).