【发布时间】:2018-07-13 23:42:01
【问题描述】:
我正在考虑在我的 UWP 应用程序中从 SQLite 切换到 Realm,因为 Realm 似乎相当容易设置,但我遇到了一些限制,到目前为止对我来说是一个交易破坏者,最重要的是显然,在处理用于检索它们的 Realm 实例之后,您不能使用领域对象。所以我想知道我应该如何加载数据以放入 ViewModel,因为在加载了 Realm 实例将消失的数据项之后。
这是一个非常基本的 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();
}
}
}
假设MyItem 是一些示例模型,它继承自RealmObject。
现在,如果我使用 SQLite,我将不会有任何问题,因为一旦从数据库中检索到,每个模型实例都将是一个独立的对象,我可以将其存储在我的 ViewModel 中。相反,从 RealObject 继承的类链接到它们原来的 Realm 实例,所以如果我在源 Realm 实例被处理后尝试使用它们(即读取它们的属性之一),一切都会崩溃(我得到了一个不错的Exception)。
显而易见的解决方法是为每个模型保留两个类:一个映射到 Realm 数据库,另一个是独立对象。但这有一些缺点:
- 课程数量翻倍
- 将每个实例复制到独立类的额外工作(和内存浪费)
- 这似乎是错误的,我的意思是,来吧
另一种可能性是保留一个永远不会关闭的 Realm 对象的单例实例,但听起来也不是一个好主意(而且在使用多个线程时也会出现问题,所以它绝对不是有效的解决方案)。
我已经看到 Realm 库的 Java 版本有一些“getRawObject”方法(或类似的方法),可以让您获得 RealmObject 的独立副本,但我想这实际上创建了一个模型实例的副本,所以听起来也不好。
我的问题是:
有没有办法获得与 SQLite 相同的灵活性,一旦加载,您可以将模型传递到您想要的任何地方(包括其他线程),在 ViewModels 中使用它们,然后最终编辑它们并传递它们回到数据库以在磁盘上更新它们?
加分项:作为另一个例子,考虑一个从 Realm 数据库加载一些项目并将它们返回给用户的库。加载后,这些对象将是只读的,这意味着即使以某种方式对其进行了修改,也不会在数据库本身上对其进行更改。我当前的解决方案是再次将每个加载的模型复制到另一个不继承自 RealmObject 的类中,但正如我所说,这根本不可扩展(想象一个有几十个模型的大型项目,这是不可能的所以)。
【问题讨论】:
-
stackoverflow.com/a/38061292/2413303 几乎是我为 .Net 找到的所有内容(而
copyFromRealm在 .NET github.com/realm/realm-dotnet/issues/661#issuecomment-336610046 中不存在) -
我创建了一个扩展函数来深度克隆对象,而不包括领域属性。请在这里查看我的答案stackoverflow.com/questions/37999630/…
-
基于answer,我创建了用于深度复制领域对象的NuGet包nuget.org/packages/Realm.Clone源代码:github.com/pfedotovsky/realm-dotnet-clone/blob/master/…