private async Task SoftDeleteAsync(TId id, CancellationToken cancellationToken) { TResource resourceFromDatabase = await GetPrimaryResourceForUpdateAsync(id, cancellationToken); ((ISoftDeletable)resourceFromDatabase).SoftDeletedAt = _systemClock.UtcNow; // A delete operation does not target any fields, so we can just pass resourceFromDatabase twice. await _repositoryAccessor.UpdateAsync(resourceFromDatabase, resourceFromDatabase, cancellationToken); }
/// <inheritdoc /> public virtual async Task <TResource> UpdateAsync(TId id, TResource resource, CancellationToken cancellationToken) { _traceWriter.LogMethodStart(new { id, resource }); ArgumentGuard.NotNull(resource, nameof(resource)); TResource resourceFromRequest = resource; _resourceChangeTracker.SetRequestedAttributeValues(resourceFromRequest); _hookExecutor.BeforeUpdateResource(resourceFromRequest); TResource resourceFromDatabase = await GetPrimaryResourceForUpdateAsync(id, cancellationToken); _resourceChangeTracker.SetInitiallyStoredAttributeValues(resourceFromDatabase); await _resourceDefinitionAccessor.OnPrepareWriteAsync(resourceFromDatabase, OperationKind.UpdateResource, cancellationToken); try { await _repositoryAccessor.UpdateAsync(resourceFromRequest, resourceFromDatabase, cancellationToken); } catch (DataStoreUpdateException) { await AssertResourcesToAssignInRelationshipsExistAsync(resourceFromRequest, cancellationToken); throw; } TResource afterResourceFromDatabase = await GetPrimaryResourceByIdAsync(id, TopFieldSelection.WithAllAttributes, cancellationToken); _hookExecutor.AfterUpdateResource(afterResourceFromDatabase); _resourceChangeTracker.SetFinallyStoredAttributeValues(afterResourceFromDatabase); bool hasImplicitChanges = _resourceChangeTracker.HasImplicitChanges(); if (!hasImplicitChanges) { return(null); } _hookExecutor.OnReturnSingle(afterResourceFromDatabase, ResourcePipeline.Patch); return(afterResourceFromDatabase); }