applyToDb method

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

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();
}