/// <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 async Task <IStatusGeneric <int> > HardDeleteSoftDeletedEntriesAsync <TEntity>(TEntity hardDeleteThisEntity, bool callSaveChanges = true)
            where TEntity : class, TInterface
        {
            if (hardDeleteThisEntity == null)
            {
                throw new ArgumentNullException(nameof(hardDeleteThisEntity));
            }
            var status = new StatusGenericHandler <int>();

            if (_config.GetSoftDeleteValue.Compile().Invoke(hardDeleteThisEntity) == 0)
            {
                return(status.AddError($"This entry isn't {_config.TextSoftDeletedPastTense}."));
            }

            //For reset you need to read every time because some of the collection might be soft deleted already
            var walker = new CascadeWalker <TInterface>(_context, _config, true,
                                                        CascadeSoftDelWhatDoing.HardDeleteSoftDeleted, true);
            await walker.WalkEntitiesSoftDelete(hardDeleteThisEntity, 1);

            if (callSaveChanges)
            {
                await _context.SaveChangesAsync();
            }

            return(ReturnSuccessFullResult(CascadeSoftDelWhatDoing.HardDeleteSoftDeleted, walker.NumFound));
        }
        /// <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 async Task <IStatusGeneric <int> > SetCascadeSoftDeleteAsync <TEntity>(TEntity softDeleteThisEntity, bool callSaveChanges = true)
            where TEntity : class, TInterface
        {
            if (softDeleteThisEntity == null)
            {
                throw new ArgumentNullException(nameof(softDeleteThisEntity));
            }
            _context.ThrowExceptionIfPrincipalOneToOne(softDeleteThisEntity);

            var status = new StatusGenericHandler <int>();

            if (_config.GetSoftDeleteValue.Compile().Invoke(softDeleteThisEntity) != 0)
            {
                return(status.AddError($"This entry is already {_config.TextSoftDeletedPastTense}."));
            }

            var walker = new CascadeWalker <TInterface>(_context, _config, true,
                                                        CascadeSoftDelWhatDoing.SoftDelete, _config.ReadEveryTime);
            await walker.WalkEntitiesSoftDelete(softDeleteThisEntity, 1);

            if (callSaveChanges)
            {
                await _context.SaveChangesAsync();
            }

            return(ReturnSuccessFullResult(CascadeSoftDelWhatDoing.SoftDelete, walker.NumFound));
        }
        /// <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
        {
            if (softDeleteThisEntity == null)
            {
                throw new ArgumentNullException(nameof(softDeleteThisEntity));
            }

            //If is a one-to-one entity we return an error
            var keys = _context.Entry(softDeleteThisEntity).Metadata.GetForeignKeys();

            if (!keys.All(x => x.DependentToPrincipal?.IsCollection == true || x.PrincipalToDependent?.IsCollection == true))
            {
                //This it is a one-to-one entity
                throw new InvalidOperationException("You cannot soft delete a one-to-one relationship. " +
                                                    "It causes problems if you try to create a new version.");
            }

            var status = new StatusGenericHandler <int>();

            if (_config.GetSoftDeleteValue.Compile().Invoke(softDeleteThisEntity) != 0)
            {
                return(status.AddError($"This entry is already {_config.TextSoftDeletedPastTense}."));
            }

            var walker = new CascadeWalker <TInterface>(_context, _config, CascadeSoftDelWhatDoing.SoftDelete, _config.ReadEveryTime);

            walker.WalkEntitiesSoftDelete(softDeleteThisEntity, 1);
            if (callSaveChanges)
            {
                _context.SaveChanges();
            }

            return(ReturnSuccessFullResult(CascadeSoftDelWhatDoing.SoftDelete, walker.NumFound));
        }
        /// <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
        {
            if (resetSoftDeleteThisEntity == null)
            {
                throw new ArgumentNullException(nameof(resetSoftDeleteThisEntity));
            }

            var status             = new StatusGenericHandler <int>();
            var currentDeleteLevel = _config.GetSoftDeleteValue.Compile().Invoke(resetSoftDeleteThisEntity);

            if (currentDeleteLevel == 0)
            {
                return(status.AddError($"This entry isn't {_config.TextSoftDeletedPastTense}."));
            }

            if (currentDeleteLevel > 1)
            {
                return(status.AddError($"This entry was soft deleted {currentDeleteLevel - 1} " +
                                       $"level{(currentDeleteLevel > 2  ? "s" : "")} above here"));
            }

            //For reset you need to read every time because some of the collection might be soft deleted already
            var walker = new CascadeWalker <TInterface>(_context, _config, false,
                                                        CascadeSoftDelWhatDoing.ResetSoftDelete, false);

            walker.WalkEntitiesSoftDelete(resetSoftDeleteThisEntity, 1).CheckSyncValueTaskWorked();;
            if (callSaveChanges)
            {
                _context.SaveChanges();
            }

            return(ReturnSuccessFullResult(CascadeSoftDelWhatDoing.ResetSoftDelete, walker.NumFound));
        }
        /// <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
        {
            if (checkHardDeleteThisEntity == null)
            {
                throw new ArgumentNullException(nameof(checkHardDeleteThisEntity));
            }
            var status = new StatusGenericHandler <int>();

            if (_config.GetSoftDeleteValue.Compile().Invoke(checkHardDeleteThisEntity) == 0)
            {
                return(status.AddError($"This entry isn't {_config.TextSoftDeletedPastTense}."));
            }

            //For reset you need to read every time because some of the collection might be soft deleted already
            var walker = new CascadeWalker <TInterface>(_context, _config, false,
                                                        CascadeSoftDelWhatDoing.CheckWhatWillDelete, _config.ReadEveryTime);
            var valueTask = walker.WalkEntitiesSoftDelete(checkHardDeleteThisEntity, 1);

            if (!valueTask.IsCompleted)
            {
                throw new InvalidOperationException("Can only run sync tasks");
            }
            return(ReturnSuccessFullResult(CascadeSoftDelWhatDoing.CheckWhatWillDelete, walker.NumFound));
        }