Skip to content
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

Update Repository DeleteAsync and DeleteManyAsync methods #7543

Merged
merged 6 commits into from
Feb 2, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public IEnumerator<TEntity> GetEnumerator()

public abstract Task DeleteAsync(Expression<Func<TEntity, bool>> predicate, bool autoSave = false, CancellationToken cancellationToken = default);

public virtual Task DeleteManyAsync(
Expression<Func<TEntity, bool>> predicate,
bool autoSave = false,
CancellationToken cancellationToken = default)
=> DeleteAsync(predicate, autoSave, cancellationToken);

maliming marked this conversation as resolved.
Show resolved Hide resolved
protected virtual TQueryable ApplyDataFilters<TQueryable>(TQueryable query)
where TQueryable : IQueryable<TEntity>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,7 @@ public override async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate
.Where(predicate)
.ToListAsync(GetCancellationToken(cancellationToken));

foreach (var entity in entities)
{
dbSet.Remove(entity);
}
await DeleteManyAsync(entities, autoSave, cancellationToken);

if (autoSave)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,19 +184,6 @@ protected virtual async Task ApplyAbpConceptsForDeletedEntityAsync(TEntity entit
return (await GetQueryableAsync()).Where(predicate).SingleOrDefault();
}

public override async Task DeleteAsync(
Expression<Func<TEntity, bool>> predicate,
bool autoSave = false,
CancellationToken cancellationToken = default)
{
var entities = (await GetQueryableAsync()).Where(predicate).ToList();

foreach (var entity in entities)
{
await DeleteAsync(entity, autoSave, cancellationToken);
}
}

public override async Task<TEntity> InsertAsync(
TEntity entity,
bool autoSave = false,
Expand Down Expand Up @@ -251,6 +238,16 @@ protected virtual async Task ApplyAbpConceptsForDeletedEntityAsync(TEntity entit
}
}

public override async Task DeleteAsync(
Expression<Func<TEntity, bool>> predicate,
bool autoSave = false,
CancellationToken cancellationToken = default)
{
var entities = (await GetQueryableAsync()).Where(predicate).ToList();

await DeleteManyAsync(entities, autoSave, cancellationToken);
}

public override async Task<List<TEntity>> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default)
{
return (await GetQueryableAsync()).ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,16 @@ public override async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool a
bool autoSave = false,
CancellationToken cancellationToken = default)
{
await ApplyAbpConceptsForDeletedEntityAsync(entity);
var oldConcurrencyStamp = SetNewConcurrencyStamp(entity);

var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken));
var collection = dbContext.Collection<TEntity>();

if (entity is ISoftDelete softDeleteEntity && !IsHardDeleted(entity))
var oldConcurrencyStamp = SetNewConcurrencyStamp(entity);

if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)) && !IsHardDeleted(entity))
{
softDeleteEntity.IsDeleted = true;
((ISoftDelete)entity).IsDeleted = true;
await ApplyAbpConceptsForDeletedEntityAsync(entity);

ReplaceOneResult result;

if (dbContext.SessionHandle != null)
Expand Down Expand Up @@ -313,6 +314,8 @@ public override async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool a
}
else
{
await ApplyAbpConceptsForDeletedEntityAsync(entity);

DeleteResult result;

if (dbContext.SessionHandle != null)
Expand Down Expand Up @@ -343,22 +346,23 @@ public override async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool a
bool autoSave = false,
CancellationToken cancellationToken = default)
{
var softDeletedEntities = new List<TEntity>();
var softDeletedEntities = new List<(TEntity Entity, string ConcurrencyStamp)>();
var hardDeletedEntities = new List<TEntity>();

foreach (var entity in entities)
{
await ApplyAbpConceptsForDeletedEntityAsync(entity);
SetNewConcurrencyStamp(entity);

if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)) && !IsHardDeleted(entity))
{
softDeletedEntities.Add(entity);
((ISoftDelete)entity).IsDeleted = true;

softDeletedEntities.Add((entity, SetNewConcurrencyStamp(entity)));
}
else
{
hardDeletedEntities.Add(entity);
}

await ApplyAbpConceptsForDeletedEntityAsync(entity);
}

var dbContext = await GetDbContextAsync(GetCancellationToken(cancellationToken));
Expand All @@ -372,26 +376,23 @@ public override async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool a

if (softDeletedEntities.Count > 0)
{
UpdateResult updateResult;
var softDeleteEntitiesCount = softDeletedEntities.Count;
BulkWriteResult updateResult;

List<WriteModel<TEntity>> replaceRequests = new List<WriteModel<TEntity>>(
softDeletedEntities.Select(entity => new ReplaceOneModel<TEntity>(
CreateEntityFilter(entity.Entity, true, entity.ConcurrencyStamp), entity.Entity))
);

if (dbContext.SessionHandle != null)
{
updateResult = await collection.UpdateManyAsync(
dbContext.SessionHandle,
CreateEntitiesFilter(softDeletedEntities),
Builders<TEntity>.Update.Set(x => ((ISoftDelete)x).IsDeleted, true)
);
updateResult = await collection.BulkWriteAsync(dbContext.SessionHandle, replaceRequests, cancellationToken: cancellationToken);
}
else
{
updateResult = await collection.UpdateManyAsync(
CreateEntitiesFilter(softDeletedEntities),
Builders<TEntity>.Update.Set(x => ((ISoftDelete)x).IsDeleted, true)
);
updateResult = await collection.BulkWriteAsync(replaceRequests, cancellationToken: cancellationToken);
}

if (updateResult.MatchedCount < softDeleteEntitiesCount)
if (updateResult.MatchedCount < softDeletedEntities.Count)
{
ThrowOptimisticConcurrencyException();
}
Expand All @@ -407,13 +408,13 @@ public override async Task UpdateManyAsync(IEnumerable<TEntity> entities, bool a
deleteResult = await collection.DeleteManyAsync(
dbContext.SessionHandle,
CreateEntitiesFilter(hardDeletedEntities)
);
);
}
else
{
deleteResult = await collection.DeleteManyAsync(
CreateEntitiesFilter(hardDeletedEntities)
);
);
}

if (deleteResult.DeletedCount < hardDeletedEntitiesCount)
Expand Down Expand Up @@ -462,10 +463,7 @@ public override async Task<long> GetCountAsync(CancellationToken cancellationTok
.Where(predicate)
.ToListAsync(cancellationToken);

foreach (var entity in entities)
{
await DeleteAsync(entity, autoSave, cancellationToken);
}
await DeleteManyAsync(entities, autoSave, cancellationToken);
}

[Obsolete("Use GetQueryableAsync method.")]
Expand Down Expand Up @@ -780,9 +778,10 @@ protected override FilterDefinition<TEntity> CreateEntityFilter(TEntity entity,
return RepositoryFilterer.CreateEntityFilter(entity, withConcurrencyStamp, concurrencyStamp);
}

// todo: This method should consider concurrencyStamp
protected override FilterDefinition<TEntity> CreateEntitiesFilter(IEnumerable<TEntity> entities, bool withConcurrencyStamp = false)
{
return RepositoryFilterer.CreateEntitiesFilter(entities, withConcurrencyStamp);
return RepositoryFilterer.CreateEntitiesFilter(entities);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,23 @@ public async Task Should_Cancel_Deletion_For_Soft_Delete_Entities_ById()
douglas.DeletionTime.ShouldNotBeNull();
}
}

[Fact]
public async Task Should_Cancel_Deletion_For_Soft_Delete_Many_Entities_ById()
{
await PersonRepository.DeleteManyAsync(new []{ TestDataBuilder.UserDouglasId });

var douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldBeNull();

using (DataFilter.Disable<ISoftDelete>())
{
douglas = await PersonRepository.FindAsync(TestDataBuilder.UserDouglasId);
douglas.ShouldNotBeNull();
douglas.IsDeleted.ShouldBeTrue();
douglas.DeletionTime.ShouldNotBeNull();
}
}

[Fact]
public async Task Should_Handle_Deletion_On_Update_For_Soft_Delete_Entities()
Expand Down