applyToDb method

void applyToDb({
  1. PutMode mode = PutMode.put,
  2. Transaction? tx,
})

Save changes made to this ToMany relation to the database. Alternatively, you can call box.put(object), its relations are automatically saved.

If this collection contains new objects (with zero IDs), applyToDb() will put them on-the-fly. For this to work the source object (the object owing this ToMany) must be already stored because its ID is required.

Implementation

void applyToDb({PutMode mode = PutMode.put, Transaction? tx}) {
  if (!_hasPendingDbChanges) return;
  _verifyAttached();

  if (_rel == null) {
    throw StateError("Relation info not initialized, can't applyToDb()");
  }

  if (_rel!.objectId == 0) {
    // This shouldn't happen but let's be a little paranoid.
    throw StateError(
        "Can't store relation info for the target object with zero ID");
  }

  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 = _entity.getId(object) ?? 0;

      switch (_rel!.type) {
        case RelType.toMany:
          if (add) {
            if (id == 0) id = InternalBoxAccess.put(_box, object, mode, tx);
            InternalBoxAccess.relPut(_otherBox, _rel!.id, _rel!.objectId, id);
          } else {
            if (id == 0) return;
            InternalBoxAccess.relRemove(
                _otherBox, _rel!.id, _rel!.objectId, id);
          }
          break;
        case RelType.toOneBacklink:
          final srcField = _rel!.toOneSourceField(object);
          srcField.targetId = add ? _rel!.objectId : null;
          _box.put(object, mode: mode);
          break;
        case RelType.toManyBacklink:
          if (add) {
            if (id == 0) id = InternalBoxAccess.put(_box, object, mode, tx);
            InternalBoxAccess.relPut(_box, _rel!.id, id, _rel!.objectId);
          } else {
            if (id == 0) return;
            InternalBoxAccess.relRemove(_box, _rel!.id, id, _rel!.objectId);
          }
          break;
        default:
          throw UnimplementedError();
      }
    });
    if (ownedTx) tx.successAndClose();
  } catch (ex) {
    // Is a no-op if successAndClose did throw.
    if (ownedTx) tx.abortAndClose();
    rethrow;
  }

  _counts.clear();
  _addedBeforeLoad.clear();
}