问题描述
我正在构建一个应用,其中 Document
有一个属于 DocumentTemplate
的 DocumentFamily
。
我正在研究应用程序的基本 CRUD 操作,我需要一个 watchDocumentTemplateById
方法来获取 DocumentTemplate
的流,但我还需要观察它的 DocumentFamily
。
问题是我不知道如何嵌套两个流,以便当 DocumentFamily
更新时,DocumentTemplate
将具有更新的 DocumentFamily
。
如果有人能告诉我正确的方法,我将不胜感激。 我使用 Flutter 和 ObjectBox 作为我的本地数据库。
这是我开始实施的方法watchDocumentTemplateById
(未完成):
@override
Stream<Either<DocumentTemplateFailure,DocumentTemplate>>
watchDocumentTemplateById(UniqueId templateId) {
return _Box
.query(DocumentTemplateEntity_.id.equals(templateId.getorCrash()))
.watch(triggerImmediately: true)
.map((query) {
final templateEntity = query.findFirst();
if (null != templateEntity) {
final familyOrFailureStream =
_documentFamilyRepository.watchDocumentFamilyById(
UniqueId.fromUniqueString(templateEntity.familyId));
familyOrFailureStream.listen((familyOrFailure) {
return familyOrFailure.fold(
(failure) =>
DocumentTemplateFailure.familyFailure(familyFailure: failure),(family) => templateEntity.todomain(family: family),);
});
}
return left(const DocumentTemplateFailure.notFound());
});
}
以及上面提到的类(DocumentTemplate、DocumentTemplateEntity、DocumentFamily 和 DocumentFamilyEntity):
文档模板:
@freezed
class DocumentTemplate with _$DocumentTemplate {
factory DocumentTemplate({
required UniqueId id,required DocumentTemplateTitle title,required double leftMargin,required double topMargin,required double rightMargin,required double bottomMargin,required DocumentFamily family,}) = _DocumentTemplate;
}
文档模板实体:
@Entity()
class DocumentTemplateEntity {
@Id()
int obid = 0;
@Unique()
String id;
String title;
double leftMargin;
double topMargin;
double rightMargin;
double bottomMargin;
String familyId;
DocumentTemplateEntity({
required this.id,required this.title,required this.leftMargin,required this.topMargin,required this.rightMargin,required this.bottomMargin,required this.familyId,});
DocumentTemplate todomain({
required DocumentFamily family,}) =>
DocumentTemplate(
id: UniqueId.fromUniqueString(id),title: DocumentTemplateTitle(title),leftMargin: leftMargin,topMargin: topMargin,rightMargin: rightMargin,bottomMargin: bottomMargin,family: family,);
factory DocumentTemplateEntity.fromDomain(DocumentTemplate template) =>
DocumentTemplateEntity(
id: template.id.getorCrash(),title: template.title.getorCrash(),leftMargin: template.leftMargin,topMargin: template.topMargin,rightMargin: template.rightMargin,bottomMargin: template.bottomMargin,familyId: template.family.id.getorCrash(),);
}
文档系列:
@freezed
class DocumentFamily with _$DocumentFamily {
factory DocumentFamily({
required UniqueId id,required int position,required String name,}) = _DocumentFamily;
}
文档家族实体:
@Entity()
class DocumentFamilyEntity {
@Id()
int obid = 0;
@Unique()
String id;
String name;
int position;
DocumentFamilyEntity({
required this.id,required this.name,required this.position,});
DocumentFamily todomain() => DocumentFamily(
id: UniqueId.fromUniqueString(id),name: name,position: position,);
factory DocumentFamilyEntity.fromDomain(DocumentFamily family) =>
DocumentFamilyEntity(
id: family.id.getorCrash(),name: family.name,position: family.position,);
}
提前致谢!
编辑:
我尝试自己解决它并找到了 switchMap
方法,该方法似乎将两个流合二为一,但我不完全确定它是否适用于更新的 watchDocumentTemplateById
方法:
参考:How do I nest Streams in Dart (map Streams to Stream events)?
@override
Stream<Either<DocumentTemplateFailure,DocumentTemplate>>
watchDocumentTemplateById(UniqueId templateId) {
return _Box
.query(DocumentTemplateEntity_.id.equals(templateId.getorCrash()))
.watch(triggerImmediately: true)
.switchMap((query) {
final templateEntity = query.findFirst();
// if(null == templateEntity) return ??? DocumentTemplateFailure.notFound();
final familyId = UniqueId.fromUniqueString(templateEntity!.familyId);
return _documentFamilyRepository.watchDocumentFamilyById(familyId).map(
(failureOrFamily) => failureOrFamily.fold(
(failure) => left(
DocumentTemplateFailure.familyFailure(familyFailure: failure),),(family) => right(
templateEntity.todomain(family: family),);
});
}
解决方法
您是否考虑过直接在 DocumentFamily
和 DocumentTemplate
类上使用 @Entity?参见 this example 显示它与包 freezed
。
在任何情况下,您可能都需要将实体之间的链接表示为 ObjectBox relation 而不仅仅是一个普通的 ID 字段。
然后 box.query().link() 创建跨实体的查询。如果你 watch()
那个,它会在基础实体以及所有链接的实体发生变化时触发。