境界如何关闭和阅读
Realm how to close and read
我遇到以下错误:Realms.Exceptions.RealmClosedException
当我在检索它们后尝试读取我的领域对象列表时。关闭领域是我想要的行为,因为在我的日志中我看到 ~2K 崩溃实例报告领域 OOM 异常所以我决定尝试将对领域的调用包装在 using
语句中,如下所示:
List<RealmDomain.User> users;
using(var realm = Realm.GetInstance(config))
{
users = realm.All<RealmDomain.User>().ToList();
}
return users;
然后我尝试按如下方式处理这些数据(这就是引发异常的时间)
allUsers.FirstOrDefault(x => x.PortalUserId == id.ToString());
。 allUsers
在这种情况下是保存最后一个代码块返回的数据的变量。因此,我想知道正确处理领域处理的正确方法是什么,以确保我们不会 运行 进入 OOM 异常,以及即使在关闭后如何从所述源正确读取数据?
编辑:returns 用户所在的块位于我的 UserRepository 中,应用程序实现了 UnitOfWork 模式(以访问我们的领域数据库),然后通过 DI 访问该模式。
Edit2:另一个后续问题是:如果它只是一个 CUD 操作(创建、更新、删除),我是否应该只将对领域的调用包装在 Using 语句中,而读取不应包装在其中并让GC 稍后根据需要处理领域实例?
我觉得你的问题其实有很多点。
处置
你处理领域的方式实际上取决于你是在主线程上还是在后台线程上。
如果你在主线程上,那么你不应该处理你的领域,并且在需要时调用 Realm.GetInstance() 或将领域初始化为单例是有意义的,比如在以下代码段中:
public class MyViewModel
{
private readonly Realm realm;
public MyViewModel()
{
this.realm = Realm.GetInstance(); //or this.realm = RealmProvider.Singleton
}
}
如果您在后台线程上,那么您肯定需要处理领域。在这种情况下,using 语句可能是最简单的做法:
public async Task OnBackgroundThread()
{
using(var realm = Realm.GetInstance()) //From C#8 you don't even need the braces
{
//do work with realm
}
}
您需要在后台线程上处理域,否则会导致磁盘上域大小的增加。您可以在 this answer.
中阅读更多有关原因的信息
ToList()
在 realm.All()
上使用 ToList()
可能不是一个好主意,因为您将加载内存中的所有对象,失去访问的“惰性”。如果您需要做的是找到某个对象,您可以使用如下查询:
realm.All<User>().Where(x => x.PortalUserId == id.ToString()).First();
存储库
Realm 不能很好地与存储库模式配合使用。如果你真的想使用存储库模式,那么你将失去使用领域的一些优势,比如对象和集合是实时的和自动更新的。此外,由于我之前所说,使用后台线程使这一切变得更加复杂。
我遇到以下错误:Realms.Exceptions.RealmClosedException
当我在检索它们后尝试读取我的领域对象列表时。关闭领域是我想要的行为,因为在我的日志中我看到 ~2K 崩溃实例报告领域 OOM 异常所以我决定尝试将对领域的调用包装在 using
语句中,如下所示:
List<RealmDomain.User> users;
using(var realm = Realm.GetInstance(config))
{
users = realm.All<RealmDomain.User>().ToList();
}
return users;
然后我尝试按如下方式处理这些数据(这就是引发异常的时间)
allUsers.FirstOrDefault(x => x.PortalUserId == id.ToString());
。 allUsers
在这种情况下是保存最后一个代码块返回的数据的变量。因此,我想知道正确处理领域处理的正确方法是什么,以确保我们不会 运行 进入 OOM 异常,以及即使在关闭后如何从所述源正确读取数据?
编辑:returns 用户所在的块位于我的 UserRepository 中,应用程序实现了 UnitOfWork 模式(以访问我们的领域数据库),然后通过 DI 访问该模式。
Edit2:另一个后续问题是:如果它只是一个 CUD 操作(创建、更新、删除),我是否应该只将对领域的调用包装在 Using 语句中,而读取不应包装在其中并让GC 稍后根据需要处理领域实例?
我觉得你的问题其实有很多点。
处置
你处理领域的方式实际上取决于你是在主线程上还是在后台线程上。
如果你在主线程上,那么你不应该处理你的领域,并且在需要时调用 Realm.GetInstance() 或将领域初始化为单例是有意义的,比如在以下代码段中:
public class MyViewModel
{
private readonly Realm realm;
public MyViewModel()
{
this.realm = Realm.GetInstance(); //or this.realm = RealmProvider.Singleton
}
}
如果您在后台线程上,那么您肯定需要处理领域。在这种情况下,using 语句可能是最简单的做法:
public async Task OnBackgroundThread()
{
using(var realm = Realm.GetInstance()) //From C#8 you don't even need the braces
{
//do work with realm
}
}
您需要在后台线程上处理域,否则会导致磁盘上域大小的增加。您可以在 this answer.
中阅读更多有关原因的信息ToList()
在 realm.All()
上使用 ToList()
可能不是一个好主意,因为您将加载内存中的所有对象,失去访问的“惰性”。如果您需要做的是找到某个对象,您可以使用如下查询:
realm.All<User>().Where(x => x.PortalUserId == id.ToString()).First();
存储库
Realm 不能很好地与存储库模式配合使用。如果你真的想使用存储库模式,那么你将失去使用领域的一些优势,比如对象和集合是实时的和自动更新的。此外,由于我之前所说,使用后台线程使这一切变得更加复杂。