VO-11 · Remplacer une collection de valeurs ne laisse pas d’orphelins
Signal
Un repository qui enregistre une collection de value objects en insérant ou en modifiant des lignes enfants, mais ne supprime jamais les lignes retirées du modèle.
Pourquoi
Quand une collection entière est remplacée, les anciens éléments doivent être supprimés du stockage. Sinon, les valeurs retirées du modèle reviennent au rechargement. Avec un ORM, vider la collection avant de la remplacer, pour que l’ORM supprime les anciens éléments.
Exceptions
Une collection sérialisée dans une seule colonne, réécrite en entier à chaque enregistrement.
Correction
Supprimer les anciennes lignes à chaque remplacement.
Adaptation
Avec un repository écrit à la main, supprimer puis réinsérer, ou calculer la différence.
Notre choix : avec Prisma, un deleteMany sur les lignes enfants suivi d’un createMany, dans la transaction du Unit of Work (REP-14).
Exemple
// Avoid: a lifted block keeps its row, and comes back on the next load
const db = this.#unitOfWork.client();
for (const row of this.#mapper.toBlockRows(wallet)) {
await db.walletBlock.upsert({
where: { walletId_reference: { walletId: row.walletId, reference: row.reference } },
create: row,
update: row,
});
}// Preferred: the wallet's blocks replace its rows, in the same transaction
const db = this.#unitOfWork.client();
await db.walletBlock.deleteMany({ where: { walletId: wallet.id.value } });
await db.walletBlock.createMany({ data: this.#mapper.toBlockRows(wallet) });Après wallet.unblock(), le blocage n’est plus dans le wallet, mais le premier bloc laisse sa ligne en base. Au prochain chargement, le blocage revient, et les débits sont de nouveau refusés.