applyToDb method
Save changes made to this ToMany relation to the database.
This is an alternative to calling box.put(object)
where object
is the
object owning this ToMany.
If this contains new objects (IDs set to 0) they will be put. This requires the object owning this ToMany to already be stored because its ID is required.
Implementation
void applyToDb(
{Store? existingStore, PutMode mode = PutMode.put, Transaction? tx}) {
if (!_hasPendingDbChanges) return;
final configuration = _getStoreConfigOrThrow();
final relInfo = configuration.relInfo;
if (relInfo.objectId == 0) {
// The ID of the object owning this is required.
throw StateError(
"Can't store relation info for the target object with zero ID");
}
// Use given store, or obtain one via store configuration
// (then store must be closed once done).
final Store store = existingStore ??
StoreInternal.attachByConfiguration(configuration.storeConfiguration);
try {
final ownedTx = tx == null;
tx ??= Transaction(store, TxMode.write);
try {
_counts.forEach((EntityT object, count) {
if (count == 0) return;
final add = count > 0; // otherwise: remove
var id = configuration.entity.getId(object) ?? 0;
switch (relInfo.type) {
case RelType.toMany:
if (add) {
if (id == 0) {
id = InternalBoxAccess.put(
configuration.box(store), object, mode, tx);
}
InternalBoxAccess.relPut(configuration.otherBox(store),
relInfo.id, relInfo.objectId, id);
} else {
if (id == 0) return;
InternalBoxAccess.relRemove(configuration.otherBox(store),
relInfo.id, relInfo.objectId, id);
}
break;
case RelType.toOneBacklink:
final srcField = relInfo.toOneSourceField(object);
srcField.targetId = add ? relInfo.objectId : null;
configuration.box(store).put(object, mode: mode);
break;
case RelType.toManyBacklink:
if (add) {
if (id == 0) {
id = InternalBoxAccess.put(
configuration.box(store), object, mode, tx);
}
InternalBoxAccess.relPut(
configuration.box(store), relInfo.id, id, relInfo.objectId);
} else {
if (id == 0) return;
InternalBoxAccess.relRemove(
configuration.box(store), relInfo.id, id, relInfo.objectId);
}
break;
default:
throw UnimplementedError();
}
});
if (ownedTx) tx.successAndClose();
} catch (ex) {
// Is a no-op if successAndClose did throw.
if (ownedTx) tx.abortAndClose();
rethrow;
}
} finally {
// If store was temporarily created, close it.
if (existingStore == null) {
store.close();
}
}
_counts.clear();
_addedBeforeLoad.clear();
}