-
Notifications
You must be signed in to change notification settings - Fork 10
Cascade Soft Delete
Jon P Smith edited this page Jan 12, 2021
·
3 revisions
Cascade Soft Delete mimics the SQL database cascade delete of dependent entities. I have written quite a bit about how this works - see this section of the first article and where it is useful in this second of the SoftDeleteServices article. I recommend you read these to see how and why it is useful.
The Cascade Soft Delete methods have nine methods, as shown below with there comments. As you can see the methods that do something return a IStatusGeneric<int>
, which can return
- Success:
- The
status.IsValid
istrue
- The
status.Result
holds a number saying how many entities were changed - 1 or more if dependents (0 means none) - The
status.Message
has a user-friendly success message, e.g. "You have soft deleted an entity and its 5 dependents".
- The
- Failure
- The
status.IsValid
isfalse
- The
status.Result
will be 0 - The
status.GetAllErrors
returns an error, e.g. "Could not find the entry you ask for."
- The
See GenericServices.StatusGeneric for more about how the status works.
Here are the sync methods. The async versions are the same, but return Task<IStatusGeneric<int>>
and have Async at the end of the method name.
/// <summary>
/// This finds the entity using its primary key(s) and then cascade soft deletes the entity any dependent entities with the correct delete behaviour
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="keyValues">primary key values</param>
/// <returns>Returns status. If not errors then Result has the number of entities that have been soft deleted. Zero if error of Not Found and notFoundAllowed is true</returns>
public IStatusGeneric<int> SetCascadeSoftDeleteViaKeys<TEntity>(params object[] keyValues)
where TEntity : class, TInterface
{
return CheckExecuteCascadeSoftDelete<TEntity>(SetCascadeSoftDelete, keyValues);
}
/// <summary>
/// This finds the entity using its primary key(s) and then resets the soft delete flag so it is now visible
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="keyValues">primary key values</param>
/// <returns>Returns status. If not errors then Result has the number of entities that have been reset. Zero if error of Not Found and notFoundAllowed is true</returns>
public IStatusGeneric<int> ResetCascadeSoftDeleteViaKeys<TEntity>(params object[] keyValues)
where TEntity : class, TInterface
{
return CheckExecuteCascadeSoftDelete<TEntity>(ResetCascadeSoftDelete, keyValues);
}
/// <summary>
/// This finds the entity using its primary key(s) and counts this entity and any dependent entities
/// that are already been cascade soft deleted and are valid to be hard deleted.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="keyValues">primary key values</param>
/// <returns>Returns status. If not errors then Message contains a message to warn what will be deleted if the HardDelete... method is called.
/// Zero if error of Not Found and notFoundAllowed is true</returns>
public IStatusGeneric<int> CheckCascadeSoftDeleteViaKeys<TEntity>(params object[] keyValues)
where TEntity : class, TInterface
{
return CheckExecuteCascadeSoftDelete<TEntity>( (entity, _) => CheckCascadeSoftDelete(entity), keyValues);
}
/// <summary>
/// This finds the entity using its primary key(s) and hard deletes this entity and any dependent entities
/// that are already been cascade soft deleted.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="keyValues">primary key values</param>
/// <returns>Returns status. If not errors then Result has the number of entities that have been hard deleted. Zero if error of Not Found and notFoundAllowed is true</returns>
public IStatusGeneric<int> HardDeleteSoftDeletedEntriesViaKeys<TEntity>(params object[] keyValues)
where TEntity : class, TInterface
{
return CheckExecuteCascadeSoftDelete<TEntity>(HardDeleteSoftDeletedEntries, keyValues);
}
/// <summary>
/// This with cascade soft delete this entity and any dependent entities with the correct delete behaviour
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="softDeleteThisEntity">entity class with cascade soft delete interface. Mustn't be null</param>
/// <param name="callSaveChanges">Defaults to calling SaveChanges. If set to false, then you must call SaveChanges</param>
/// <returns>Returns a status. If no errors then Result contains the number of entities that had been cascaded deleted, plus summary string in Message part</returns>
public IStatusGeneric<int> SetCascadeSoftDelete<TEntity>(TEntity softDeleteThisEntity, bool callSaveChanges = true)
where TEntity : class, TInterface
/// <summary>
/// This will result the cascade soft delete flag on this entity and any dependent entities with the correct delete behaviour and cascade level
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="resetSoftDeleteThisEntity">entity class with cascade soft delete interface. Mustn't be null</param>
/// <param name="callSaveChanges">Defaults to calling SaveChanges. If set to false, then you must call SaveChanges</param>
/// <returns>Returns a status. If no errors then Result contains the number of entities that had been reset, plus summary string in Message part</returns>
public IStatusGeneric<int> ResetCascadeSoftDelete<TEntity>(TEntity resetSoftDeleteThisEntity, bool callSaveChanges = true)
where TEntity : class, TInterface
/// <summary>
/// This looks for this entity and any dependent entities that are already been cascade soft deleted and are valid to be hard deleted.
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="checkHardDeleteThisEntity">entity class with cascade soft delete interface. Mustn't be null</param>
/// <returns>Returns a status. If no errors then Result contains the number of entities which are eligible for hard delete, plus summary string in Message part</returns>
public IStatusGeneric<int> CheckCascadeSoftDelete<TEntity>(TEntity checkHardDeleteThisEntity)
where TEntity : class, TInterface
/// <summary>
/// This hard deletes this entity and any dependent entities that are already been cascade soft deleted
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="hardDeleteThisEntity">entity class with cascade soft delete interface. Mustn't be null</param>
/// <param name="callSaveChanges">Defaults to calling SaveChanges. If set to false, then you must call SaveChanges</param>
/// <returns>Returns a status. If no errors then Result contains the number of entities which were hard deleted, plus summary string in Message part</returns>
public IStatusGeneric<int> HardDeleteSoftDeletedEntries<TEntity>(TEntity hardDeleteThisEntity, bool callSaveChanges = true)
where TEntity : class, TInterface
/// <summary>
/// This returns the cascade soft deleted entities of type TEntity that can be reset, i.e. SoftDeleteLevel == 1
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <returns></returns>
public IQueryable<TEntity> GetSoftDeletedEntries<TEntity>()
where TEntity : class, TInterface
Notes:
- The Cascade Soft Delete has an extra method called
CheckCascadeSoftDelete
, which the Single Soft Delete hasn't got. The idea you might want to see what you are going to delete. It returns a message such as "Are you sure you want to hard delete this entity and its 12 dependents". - The
bool callSaveChanges = true
parameter on the methods that take in an entity class. This is there in case you want to do lots of changes together and want to callSaveChanges
yourself so they are all saved at the same time.