C# 如何关闭和读取

C# 如何关闭和读取,c#,xamarin,realm,C#,Xamarin,Realm,我遇到了一个问题,遇到了以下错误:Realms.Exceptions.RealmClosedException 当我试图在检索到领域对象后读取它们时。关闭领域是我想要的行为,因为在我的日志中,我看到了~2K个报告领域OOM异常的崩溃实例,因此我决定尝试使用语句将对领域的调用包装在中,如下所示: List<RealmDomain.User> users; using(var realm = Realm.GetInstance(config)) { users = realm.

我遇到了一个问题,遇到了以下错误:
Realms.Exceptions.RealmClosedException
当我试图在检索到领域对象后读取它们时。关闭领域是我想要的行为,因为在我的日志中,我看到了~2K个报告领域OOM异常的崩溃实例,因此我决定尝试使用语句将对领域的调用包装在
中,如下所示:

List<RealmDomain.User> users;

using(var realm = Realm.GetInstance(config))
{
    users = realm.All<RealmDomain.User>().ToList();
}

return users;
列出用户;
使用(var realm=realm.GetInstance(config))
{
users=realm.All().ToList();
}
返回用户;
然后,我尝试如下处理这些数据(即引发异常时)
allUsers.FirstOrDefault(x=>x.PortalUserId==id.ToString())
allUsers
在这种情况下是保存最后一块代码返回的数据的变量。因此,我想知道什么是正确处理领域处理的正确方法,以确保我们不会遇到OOM异常,以及如何正确读取来自所述源的数据,即使它已关闭

编辑:返回用户的块在我的UserRepository中,应用程序实现UnitOfWork模式(访问我们的领域数据库),然后通过DI访问该模式


Edit2:另一个后续问题是:如果对realm的调用只是CUD操作(创建、更新、删除),那么我是否应该只将其包装在Using语句中,而读取操作不应该包装在该语句中,然后让GC根据需要处理realm实例?

我认为您的问题实际上有多个要点

处置 处理域的方式实际上取决于您是在主线程上还是在后台线程上

如果您在主线程上,则不应处置您的领域,在需要时调用realm.GetInstance(),或者将领域初始化为单例,这是有意义的,如以下代码段中所示:

公共类MyViewModel
{
私有只读域;
公共MyViewModel()
{
this.realm=realm.GetInstance();//或this.realm=RealmProvider.Singleton
}
} 
如果你在后台线程上,那么你肯定需要处理这个领域。在这种情况下,使用语句可能是最容易做到的:

OnBackgroundThread()上的公共异步任务
{
使用C#8中的(var realm=realm.GetInstance())//甚至不需要大括号
{
//与领域一起工作
}
} 
您需要在后台线程上处理域,否则将导致磁盘上域的大小增加。你可以阅读更多关于为什么在

托利斯特() 在
realm.All()
上使用
ToList()
可能不是一个好主意,因为您将加载内存中的所有对象,从而失去访问的“惰性”。如果需要查找某个对象,可以使用以下查询:

realm.All<User>().Where(x => x.PortalUserId == id.ToString()).First();
realm.All().Where(x=>x.PortalUserId==id.ToString()).First();
存储库
Realm与存储库模式不太兼容。如果您真的想使用存储库模式,那么您将失去使用领域的一些优势,比如对象和集合是活动的并且是自动更新的。此外,由于我之前所说的,背景线程的使用使得这一切变得更加复杂。

我认为你的问题实际上有多个要点

处置 处理域的方式实际上取决于您是在主线程上还是在后台线程上

如果您在主线程上,则不应处置您的领域,在需要时调用realm.GetInstance(),或者将领域初始化为单例,这是有意义的,如以下代码段中所示:

公共类MyViewModel
{
私有只读域;
公共MyViewModel()
{
this.realm=realm.GetInstance();//或this.realm=RealmProvider.Singleton
}
} 
如果你在后台线程上,那么你肯定需要处理这个领域。在这种情况下,使用语句可能是最容易做到的:

OnBackgroundThread()上的公共异步任务
{
使用C#8中的(var realm=realm.GetInstance())//甚至不需要大括号
{
//与领域一起工作
}
} 
您需要在后台线程上处理域,否则将导致磁盘上域的大小增加。你可以阅读更多关于为什么在

托利斯特() 在
realm.All()
上使用
ToList()
可能不是一个好主意,因为您将加载内存中的所有对象,从而失去访问的“惰性”。如果需要查找某个对象,可以使用以下查询:

realm.All<User>().Where(x => x.PortalUserId == id.ToString()).First();
realm.All().Where(x=>x.PortalUserId==id.ToString()).First();
存储库
Realm与存储库模式不太兼容。如果您真的想使用存储库模式,那么您将失去使用领域的一些优势,比如对象和集合是活动的并且是自动更新的。此外,由于使用后台线程,这一切变得更加复杂,因为我之前已经说过。

通常,您可以在应用程序的生命周期内(在每个平台的应用程序生命周期之后)保持UI线程实例打开,在应用程序关闭时应调用Dispose。如果您在后台线程上,并且在该线程上获得同一RealmConfiguration基础的多个领域实例,那么它们实际上都是同一领域实例(Realm.IsSameInstance)。您可以对每个实例调用Dispose,但在该线程上的所有实例都被释放之前,不会实际关闭(Realm.IsClosed)该实例。通常,您可以在应用程序的生命周期期间(在每个平台的应用程序生命周期之后)保持UI线程实例打开,但应在应用程序关闭时调用Dispose。如果您在后台线程上并获得多个