loadCollections<C, P> method
Future<Map<EntityEntry<P> , List<C> > >
loadCollections<C, P>(
- ForeignKey<
C, P> relation, - Iterable<
EntityEntry< parentsP> >
Loads children for parents in batches.
Implementation
Future<Map<EntityEntry<P>, List<C>>> loadCollections<C, P>(
ForeignKey<C, P> relation, Iterable<EntityEntry<P>> parents) {
final entries = List<EntityEntry<P>>.of(parents);
_checkRegisteredRelationship(this, relation);
for (final entry in entries) {
_checkRelationshipEntry(entry, relation.parent);
if (!identical(entry.context, this)) {
throw const OrmStateException(
'Relationship entries belong to different contexts');
}
}
return _serialize(() async {
final result = Map<EntityEntry<P>, List<C>>.identity();
final wanted = <EntityKey, EntityEntry<P>>{};
for (final entry in entries) {
_checkRelationshipEntry(entry, relation.parent);
result[entry] = [];
final key =
_relationshipEntityKey(relation.targetColumns, entry.entity);
if (key == null) continue;
final previous = wanted[key];
if (previous != null && !identical(previous, entry)) {
throw const OrmStateException(
'Tracked parents have ambiguous relationship target values');
}
wanted[key] = entry;
}
for (final chunk
in _relationshipChunks(wanted.keys, relation.columns.length)) {
final predicate = _relationshipPredicate(relation.columns, chunk);
final rows = await connection.query(
'SELECT ${_relationshipProjection(relation.child)} '
'FROM ${quoteIdentifier(relation.child.tableName)} '
'WHERE ${predicate.$1}',
predicate.$2);
for (final values in rows.rows) {
_materialize(
relation.child, _relationshipReader(rows.columns, values));
}
}
// Current tracked FK values and explicit links take precedence over old
// store values. This also includes newly linked, unsaved children.
for (final candidate in _entries.values.toList(growable: false)) {
if (!identical(candidate.type, relation.child) ||
candidate.state == EntityState.deleted ||
candidate.state == EntityState.detached) {
continue;
}
final child = candidate as EntityEntry<C>;
EntityEntry<P>? parent;
final links = _relationshipLinks[child];
if (links != null && links.containsKey(relation)) {
_validateRelationshipLinks(child);
parent = links[relation] as EntityEntry<P>?;
} else {
final key = _relationshipEntityKey(relation.columns, child.entity);
if (key != null) parent = wanted[key];
}
if (parent != null && result.containsKey(parent)) {
result[parent]!.add(child.entity);
}
}
return Map<EntityEntry<P>, List<C>>.unmodifiable({
for (final entry in result.entries)
entry.key: List<C>.unmodifiable(entry.value)
});
});
}