New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use IBasicRepository.DeleteManyAsync in RepositoryExtensions.HardDeleteAsync #7453
Use IBasicRepository.DeleteManyAsync in RepositoryExtensions.HardDeleteAsync #7453
Conversation
I think the build is failing on the MongoDB tests because the abp/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs Line 340 in c4e0c63
abp/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs Line 261 in c4e0c63
Replace See the code... public override async Task DeleteManyAsync(
IEnumerable<TEntity> entities,
bool autoSave = false,
CancellationToken cancellationToken = default)
{
var entityArray = entities.ToArray();
foreach (var entity in entityArray)
{
await ApplyAbpConceptsForDeletedEntityAsync(entity);
SetNewConcurrencyStamp(entity);
}
var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken));
var collection = dbContext.Collection<TEntity>();
if (BulkOperationProvider != null)
{
await BulkOperationProvider.DeleteManyAsync(this, entityArray, dbContext.SessionHandle, autoSave, cancellationToken);
return;
}
var entitiesCount = entityArray.Count();
if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)))
{
var softEntityArray = entities.Where(entity => !IsHardDeleted(entity)).ToArray();
var softEntitiesCount = softEntityArray.Count();
if (softEntitiesCount > 0)
{
UpdateResult updateResult;
if (dbContext.SessionHandle != null)
{
updateResult = await collection.UpdateManyAsync(
dbContext.SessionHandle,
CreateEntitiesFilter(softEntityArray),
Builders<TEntity>.Update.Set(x => ((ISoftDelete)x).IsDeleted, true)
);
}
else
{
updateResult = await collection.UpdateManyAsync(
CreateEntitiesFilter(softEntityArray),
Builders<TEntity>.Update.Set(x => ((ISoftDelete)x).IsDeleted, true)
);
}
if (updateResult.MatchedCount < softEntitiesCount)
{
ThrowOptimisticConcurrencyException();
}
}
var hardEntityArray = entities.Except(softEntityArray).ToArray();
var hardEntitiesCount = hardEntityArray.Count();
if (hardEntitiesCount > 0)
{
DeleteResult deleteResult;
if (dbContext.SessionHandle != null)
{
deleteResult = await collection.DeleteManyAsync(
dbContext.SessionHandle,
CreateEntitiesFilter(hardEntityArray)
);
}
else
{
deleteResult = await collection.DeleteManyAsync(
CreateEntitiesFilter(hardEntityArray)
);
}
if (deleteResult.DeletedCount < hardEntitiesCount)
{
ThrowOptimisticConcurrencyException();
}
}
}
else
{
DeleteResult deleteResult;
if (dbContext.SessionHandle != null)
{
deleteResult = await collection.DeleteManyAsync(
dbContext.SessionHandle,
CreateEntitiesFilter(entityArray)
);
}
else
{
deleteResult = await collection.DeleteManyAsync(
CreateEntitiesFilter(entityArray)
);
}
if (deleteResult.DeletedCount < entitiesCount)
{
ThrowOptimisticConcurrencyException();
}
}
} |
Thanks @olicooper |
Are we happy with this implementation? Should I add a public static async Task HardDeleteAsync<TEntity>(
this IBasicRepository<TEntity> repository,
IEnumerable<TEntity> entities,
bool autoSave = false,
CancellationToken cancellationToken = default
)
where TEntity : class, IEntity, ISoftDelete
{
if (!(ProxyHelper.UnProxy(repository) is IUnitOfWorkManagerAccessor unitOfWorkManagerAccessor))
{
throw new AbpException($"The given repository (of type {repository.GetType().AssemblyQualifiedName}) should implement the {typeof(IUnitOfWorkManagerAccessor).AssemblyQualifiedName} interface in order to invoke the {nameof(HardDeleteAsync)} method!");
}
var uowManager = unitOfWorkManagerAccessor.UnitOfWorkManager;
if (uowManager == null)
{
throw new AbpException($"{nameof(unitOfWorkManagerAccessor.UnitOfWorkManager)} property of the given {nameof(repository)} object is null!");
}
if (uowManager.Current == null)
{
using (var uow = uowManager.Begin())
{
await HardDeleteWithUnitOfWorkAsync(repository, entities, autoSave, cancellationToken, uowManager.Current);
await uow.CompleteAsync(cancellationToken);
}
}
else
{
await HardDeleteWithUnitOfWorkAsync(repository, entities, autoSave, cancellationToken, uowManager.Current);
}
} I haven't done this so far because my concern is that you can write the following without compile errors: |
hi I think developers need to pay attention to this, The same thing exists in our Repository. You can add |
This relates to the recently implemented bulk operations. This PR should make
RepositoryExtensions.HardDeleteAsync
more performant when deleting collections of entities with a predicate, whilst not being a breaking change.I considered creating a new
HardDeleteManyAsync(Expression...)
method, but it seems redundant given thatIRepository
providers who don't support bulk delete will just cycle the IEnumerable anyway and we would have to duplicate the hard delete code for no obvious benefit.This PR is currently missing a
HardDeleteManyAsync(IEnumerable<TEntity>...)
method to delete collections of already fetched entities. I wasn't sure where to place it so I was thinking about creating a new issue instead.