我有以下课程:
import 'package:equatable/equatable.dart';
import 'package:objectbox/objectbox.dart';
@Entity()
/*
All fields of a class which extends Equatable should be immutable, but ObjectBox
requires the `id` field to be mutable because its value is set after an instance of
the class has been created. Because of this, we ignore the linter rule
"must_be_immutable" on all ObjectBox entities.
*/
// ignore: must_be_immutable
class Foo extends Equatable {
int id;
final String fooProp;
// I don't need a backlink yet, but very likely will in the future
// @Backlink()
// final ToMany<Bar> bars;
Foo(
this.fooProp,
{
this.id=0,
}
);
@override
List<Object> get props => [fooProp];
}
import 'package:equatable/equatable.dart';
import 'package:objectbox/objectbox.dart';
@Entity()
/*
All fields of a class which extends Equatable should be immutable, but ObjectBox
requires the `id` field to be mutable because its value is set after an instance of
the class has been created. Because of this, we ignore the linter rule
"must_be_immutable" on all ObjectBox entities.
*/
// ignore: must_be_immutable
class Bar extends Equatable {
int id;
final String barProp;
final ToMany<Foo> foos;
Bar(
this.barProp,
this.foos,
{
this.id=0,
}
);
@override
List<Object> get props => [barProp, foos];
}
这就是我要做的
import 'package:foo_bar/objectbox/objectbox.dart';
// Get previously stored instance of Foo
Foo foo = ObjectBox.fooBox.get(1);
// Print foo.fooProp
print(foo.fooProp); // Prints "asdf"
// Change foo.fooProp to something else
foo.fooProp = 'fdsa';
// Update foo
ObjectBox.fooBox.put(foo);
// Get the same instance of Foo again
foo = ObjectBox.fooBox.get(1);
// Check foo.fooProp to make sure it updated
print(foo.fooProp); // Prints "fdsa", good so far
// Get previously stored instance of Bar which has Foo instance with ID of 1 in its foos
Bar bar = ObjectBox.barBox.get(1);
// Get our foo from bar.foos
foo = bar.foos[0];
// Verify the ID of foo to make sure it is the same object
print(foo.id); // Prints "1", exactly what we expect
// Print foo.fooProp
print(foo.fooProp); // Prints "asdf", not the expected "fdsa"
该文件对这一问题作了如下说明:
请注意,to-many关系在第一次访问时被延迟解析,然后缓存在ToMany对象内的源实体中。因此,对任何方法(如ToMany对象的size())的后续调用都不会查询数据库,即使关系在其他地方发生了更改。要获取最新数据,请再次获取源实体或在ToMany对象上调用reset()。reset()
方法在ObjectBox的Flutter风格中似乎不可用,并且我们可以从我的示例中看到,即使获取ToMany
关系的双方也不会导致预期的更新。
我错过了什么?
- 失败的解决方法:**
我试着用下面这段糟糕的代码来解决这个问题,但即使这样也不起作用。ObjectBox完全忽略了实际的bar.foos
,并且为foos
持久化的内容仍然存在,不会更新。
final List<Bar> oldBars = ObjectBox.barBox.getAll();
List<Bar> newBars = [];
for(Bar oldBar in oldBars) {
if(oldBar.foos.isNotEmpty) {
List<int> oldFooIds = oldBar.foos.map((foo) => foo.id).toList();
List<Foo> newFoos = foos.where((foo) => oldFooIds.contains(foo.id)).toList();
Bar newBar = oldBar.copy(foos: ToMany<Foo>(items: newFoos));
newBars.add(newBar);
}
}
ObjectBox.barBox.putMany(newBars);
这让我觉得我的关系设置方式有问题,但是当ObjectBox生成器运行时没有错误
CALL flutter pub run build_runner build --delete-conflicting-outputs
- 更新日期:**
我现在可以工作了,但是没有清理它。我设置了Bar
构造函数来接受Foo
对象的集合,但是传入Foo
的示例是导致关系中断的原因。如果我创建Bar
的示例,然后使用bar.foos.add(foo)
,则结果与预期的一样。无论如何,这就是文档中的例子如何显示与关系的交互,我只是不认为它是字面上的,因为用这种方式创建新的对象是一件麻烦的事。我认为可以在构造函数中做一些工作,使事情变得更容易。
1条答案
按热度按时间wnavrhmk1#
这个问题的一个“解决方案”(我不严格地使用这个术语)是对
Bar
类进行如下修改,这允许我使用预先构建的x1m2 n1 a示例列表来初始化Bar
示例。对于创建新对象来说,这很好用,但是因为我想使用
Equatable
,所以我必须使所有用于确定相等性的属性都是final
。当一个类是一个@Entity
,它将持久化到ObjectBox中时,它的大多数属性通常将用于确定相等性。所以Equatable
的这个需求使得它在更新对象时与ObjectBox不一致,例如,如果我有一个Bar
的示例,我不能更新barProp
;我必须创建一个Bar
的新示例,它将barProp
初始化为所需的值。如果我创建一个Bar
的新示例,它具有barProp
所需的值foos
,并且具有与Bar
的已持久化示例相同的ID,那么我将尝试持久化该新示例。barProp
将按预期进行更新,但foos
不会。要说的是,在持久化Bar
的新示例之前,我首先必须采取调用ObjectBox.barBox.remove()
或ObjectBox.barBox.removeAll()
(取决于应用程序)的繁重方法。时间会证明像这样调用
remove
和removeAll
是否比不使用Equatable
对性能造成更大的影响,对于阅读本文的其他人来说,这种判断将取决于您的特定应用程序(例如,由于包含Equatable
,您的应用是否有更多的UI交互可受益于构建版本的减少,或者您的应用是否有更多ObjectBox交互,过多调用remove
和removeAll
会导致性能下降)。