SoftDelete: Can't set flag deletedBy, deletedAt

Viewed 1992

When I delete entity with softDelete column deletedAt and deletedBy are null or not set.

If I try softRemove, it only sets the deletedAt flag.

Here are some code for the entities:

@DeleteDateColumn({ name: 'deleted_at'})
deletedAt: Date;

@Column({ type: 'varchar', name: 'deleted_by', nullable: true })
deletedBy: string;

And for the services:

public async delete(id: string): Promise<void> {
    const talent: Talent = await this.talentRepository.findOne(id);

    if (!talent) throw new NotFoundException(`Talent with ID ${id} Not Found`);

    talent.deletedBy = "John Doe";

    await this.talentRepository.softDelete(talent);
}

If I log this service, the parameter deletedBy is set to "John Doe" but database is null.

2 Answers

Soft delete will only update the deletedAt column. If you want to update the deletedBy you should execute it separately as an update query.

From the source code documentation:

softDelete:

    /**
     * Records the delete date of entities by a given condition(s).
     * Unlike save method executes a primitive operation without cascades, relations and other operations included.
     * Executes fast and efficient DELETE query.
     * Does not check if entity exist in the database.
     * Condition(s) cannot be empty.
     */

softRemove:

   /**
     * Records the delete date of all given entities.
     */

An optional solution could be:

public async delete(id: string): Promise<void> {
    const talent: Talent = await this.talentRepository.findOne(id);

    if (!talent) throw new NotFoundException(`Talent with ID ${id} Not Found`);

    talent.deletedBy = "John Doe";

    await this.talentRepository.save(talent);
    await this.talentRepository.softDelete(talent);
}

Or within a transaction:

    public async delete(id: string): Promise<void> {
        const talent: Talent = await this.talentRepository.findOne(id);

        if (!talent) throw new NotFoundException(`Talent with ID ${id} Not Found`);

        talent.deletedBy = "John Doe";

        await this.talentRepository
            .manager
            .transaction(em => {
                await em.save(Talent, talent);
                return em.softDelete(Talent, talent);
            });
    }

TypeORM updates only deletedAt column when you use softDelete()

As an optimized version of other answers, you can update deletedBy or any other custom column you added by less DB calls(2) and less no of lines using this approach:

public async delete(id: string): Promise<void> {
    const talent: Talent = await this.talentRepository.createQueryBuilder().update(Talent).set({ deletedBy: "John Doe" }).where('id = :id', { id }).execute();

    if (!talent) throw new NotFoundException(`Talent with ID ${id} Not Found`);

    await this.talentRepository.softDelete(talent);
}

This snippet will run two DB update queries.

Related