diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs index 35d75629b0f..308b7d98ed8 100644 --- a/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs @@ -82,6 +82,28 @@ await Collection.InsertOneAsync( return entity; } + public override async Task InsertManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default) + { + foreach (var entity in entities) + { + await ApplyAbpConceptsForAddedEntityAsync(entity); + } + + if (SessionHandle != null) + { + await Collection.InsertManyAsync( + SessionHandle, + entities, + cancellationToken: cancellationToken); + } + else + { + await Collection.InsertManyAsync( + entities, + cancellationToken: cancellationToken); + } + } + public async override Task UpdateAsync( TEntity entity, bool autoSave = false, @@ -132,6 +154,55 @@ public async override Task UpdateAsync( return entity; } + public override async Task UpdateManyAsync(IEnumerable entities, bool autoSave = false, CancellationToken cancellationToken = default) + { + var isSoftDeleteEntity = typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity)); + + foreach (var entity in entities) + { + SetModificationAuditProperties(entity); + + if (isSoftDeleteEntity) + { + SetDeletionAuditProperties(entity); + await TriggerEntityDeleteEventsAsync(entity); + } + else + { + await TriggerEntityUpdateEventsAsync(entity); + } + + await TriggerDomainEventsAsync(entity); + + SetNewConcurrencyStamp(entity); + } + + var entitiesCount = entities.Count(); + BulkWriteResult result; + + if (SessionHandle != null) + { + result = await Collection.BulkWriteAsync(SessionHandle, GetReplaceRequests()); + } + else + { + result = await Collection.BulkWriteAsync(GetReplaceRequests()); + } + + if (result.MatchedCount < entitiesCount) + { + ThrowOptimisticConcurrencyException(); + } + + IEnumerable> GetReplaceRequests() + { + foreach (var entity in entities) + { + yield return new ReplaceOneModel(CreateEntityFilter(entity), entity); + } + } + } + public async override Task DeleteAsync( TEntity entity, bool autoSave = false, @@ -195,6 +266,67 @@ public async override Task DeleteAsync( } } + public override async Task DeleteManyAsync( + IEnumerable entities, + bool autoSave = false, + CancellationToken cancellationToken = default) + { + foreach (var entity in entities) + { + await ApplyAbpConceptsForDeletedEntityAsync(entity); + var oldConcurrencyStamp = SetNewConcurrencyStamp(entity); + } + + var entitiesCount = entities.Count(); + + if (typeof(ISoftDelete).IsAssignableFrom(typeof(TEntity))) + { + UpdateResult updateResult; + if (SessionHandle != null) + { + updateResult = await Collection.UpdateManyAsync( + SessionHandle, + CreateEntitiesFilter(entities), + Builders.Update.Set(x => ((ISoftDelete)x).IsDeleted, true) + ); + } + else + { + updateResult = await Collection.UpdateManyAsync( + CreateEntitiesFilter(entities), + Builders.Update.Set(x => ((ISoftDelete)x).IsDeleted, true) + ); + } + + if (updateResult.MatchedCount < entitiesCount) + { + ThrowOptimisticConcurrencyException(); + } + } + else + { + DeleteResult deleteResult; + if (SessionHandle != null) + { + deleteResult = await Collection.DeleteManyAsync( + SessionHandle, + CreateEntitiesFilter(entities) + ); + } + else + { + deleteResult = await Collection.DeleteManyAsync( + CreateEntitiesFilter(entities) + ); + } + + if (deleteResult.DeletedCount < entitiesCount) + { + ThrowOptimisticConcurrencyException(); + } + } + } + public async override Task> GetListAsync(bool includeDetails = false, CancellationToken cancellationToken = default) { return await GetMongoQueryable().ToListAsync(GetCancellationToken(cancellationToken)); @@ -271,6 +403,13 @@ protected virtual FilterDefinition CreateEntityFilter(TEntity entity, b ); } + protected virtual FilterDefinition CreateEntitiesFilter(IEnumerable entities, bool withConcurrencyStamp = false) + { + throw new NotImplementedException( + $"{nameof(CreateEntitiesFilter)} is not implemented for MongoDB by default. It should be overriden and implemented by the deriving class!" + ); + } + protected virtual async Task ApplyAbpConceptsForAddedEntityAsync(TEntity entity) { CheckAndSetId(entity); @@ -483,9 +622,14 @@ protected override FilterDefinition CreateEntityFilter(TEntity entity, return RepositoryFilterer.CreateEntityFilter(entity, withConcurrencyStamp, concurrencyStamp); } + protected override FilterDefinition CreateEntitiesFilter(IEnumerable entities, bool withConcurrencyStamp = false) + { + return RepositoryFilterer.CreateEntitiesFilter(entities, withConcurrencyStamp); + } + public async Task DeleteManyAsync([NotNull] IEnumerable ids, bool autoSave = false, CancellationToken cancellationToken = default) { - throw new NotImplementedException(); + } } }