C# 在处理领域之后,是否可以在ViewModel中使用RealmObject?

C# 在处理领域之后,是否可以在ViewModel中使用RealmObject?,c#,.net,mvvm,uwp,realm,C#,.net,Mvvm,Uwp,Realm,我正在考虑在我的UWP应用程序中从SQLite切换到Realm,因为Realm似乎更容易设置,但我遇到了一些限制,到目前为止,这些限制对我来说是一个破坏者,最重要的一个是,显然在处理用于检索Realm对象的Realm实例之后,您不能使用Realm对象。所以我想知道我应该如何加载数据以将其放入ViewModel,因为在加载数据项之后,Realm实例将消失 下面是一个非常基本的ViewModel示例: public class MyViewModel : ViewModelBase // Assum

我正在考虑在我的UWP应用程序中从SQLite切换到Realm,因为Realm似乎更容易设置,但我遇到了一些限制,到目前为止,这些限制对我来说是一个破坏者,最重要的一个是,显然在处理用于检索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继承的类链接到它们的原始领域实例,因此如果我尝试使用它们,例如,在源领域实例被释放后读取它们的一个属性,一切都会崩溃,我会得到一个很好的异常

显而易见的解决方法是为每个模型保留两个类:一个映射到领域数据库,另一个是独立对象。但这也有一些缺点:

班级数量的两倍 将每个实例复制到独立类会产生额外的工作和内存浪费 这似乎不对,我是说,来吧 另一种可能是保留一个永远不会关闭的领域对象的单实例,但听起来也不是一个好主意,而且在使用多个线程时也会出现问题,因此这绝对不是一个有效的解决方案

我已经看到,领域库的Java版本有一些getRawObject方法或类似的方法,允许您获取RealmObject的独立副本,但是,我猜这实际上创建了模型实例的副本,因此听起来也不太好

我的问题是:

是否有一种方法可以获得SQLite的同样灵活性,一旦加载,您可以将模型传递到任何您想要的地方,包括其他线程,在ViewModels中使用它们,然后最终编辑它们并将它们传递回数据库以在磁盘上更新它们


奖金点:作为另一个例子,考虑一个从领域数据库加载一些项目并将它们返回给用户的库。一旦加载,这些对象将是只读的,这意味着即使它们以某种方式被修改,它们也不会在数据库本身上被更改。我目前的解决方案是再次将每个加载的模型复制到另一个不从RealmObject继承的类中,但正如我所说的,这是不可伸缩的。想象一个有几十个模型的大型项目,这是不可能做到的。

在.NET中,似乎只有在以某种方式创建托管RealmObject的副本时,才有可能将其从域中分离

从技术上讲,它不必是一个不同的类,但它需要用新类创建


至于必须制作一个副本,好吧,这也是你一直对SQLite所做的

这几乎是我在.Net中找到的所有内容,而且.Net中不存在copyFromRealm。我创建了一个扩展函数,用于深度克隆对象,但不包括领域属性。请检查我的答案,我已经为深度复制领域对象创建了NuGet包源代码:好的,这样更好,至少我可以重用相同的类。尽管如此,我将来肯定会坚持使用SQLite,尽管这种方法不可扩展,除了不能间接继承RealObject的缺点外,还必须为每个类手动实现一个复制方法。另外,我不确定我是否理解你的意思,这也是你一直对SQLite所做的。在那里,我可以从数据库中加载模型,并在任何地方使用它们,如果我想更新它们,我可以将它们传回哪里进行复制?诀窍是Realm java通过注释处理生成这种映射。我想网络版没有。我所说的复制是指您应该像对待模式定义CREATE TABLE之类的东西一样对待RealmObject类。所以在SQLite中,您有一个SQL模式,但在Realm中,您的对象就是模式。附加的对象在技术上仍然属于领域世界。因此,当您从SQLite映射到实际实体时,这就像将托管映射到非托管。除Realm允许使用直接管理的模式对象外,它提供了延迟加载和观察能力。这与我在SQLite.NET lib中的SQLite中的模式完全相同,我指的是由EntityFramework类引擎支持的版本。因此,您只需使用属性将属性映射到类似于Realm的表列,然后所有查询和数据库操作都由库处理,您只需传递LINQ表达式,它们就会转换为查询并映射回对象。但是,模式
l实例在那里是100%独立的,并且也没有绑定到线程,因此它更灵活。此外,您可以使用间接继承,而不会出现与RealmObject不同的问题。无论如何,我将答案标记为有效,因为它实际上回答了我的问题,很好。没有现成的支持将对象从领域中分离,因为这是一个定义不明确的通用需求。例如,如果您的对象有其他对象的集合,那么这些对象是否也应该分离?然后,如果存在周期,是否应该为您解决这些问题,等等。有许多工具专门设计用于将一个对象映射到另一个对象,例如AutoMapper,这将为您省去手动复制对象的痛苦。
public Contact ToStandalone()
{
    return new Contact()
    {
        companyName = this.companyName,
        dateAdded = this.dateAdded,
        fullName = this.fullName,
        gender = this.gender,
        website = this.website
    };
}