diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs index 70332d54fc..da915626a8 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/IRepository.cs @@ -68,6 +68,20 @@ public interface IRepository : IReadOnlyRepository, IBasicRepo bool autoSave = false, CancellationToken cancellationToken = default ); + + /// + /// Deletes all entities those fit to the given predicate. + /// It directly deletes entities from database, without fetching them. + /// Some features (like soft-delete, multi-tenancy and audit logging) won't work, so use this method carefully when you need it. + /// Use the DeleteAsync method if you need to these features. + /// + /// A condition to filter entities + /// A to observe while waiting for the task to complete. + /// + Task DeleteDirectAsync( + [NotNull] Expression> predicate, + CancellationToken cancellationToken = default + ); } public interface IRepository : IRepository, IReadOnlyRepository, IBasicRepository diff --git a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs index dbdadcccdb..d843584fc4 100644 --- a/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs +++ b/framework/src/Volo.Abp.Ddd.Domain/Volo/Abp/Domain/Repositories/RepositoryBase.cs @@ -63,6 +63,8 @@ public abstract class RepositoryBase : BasicRepositoryBase, IR public abstract Task DeleteAsync(Expression> predicate, bool autoSave = false, CancellationToken cancellationToken = default); + public abstract Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default); + protected virtual TQueryable ApplyDataFilters(TQueryable query) where TQueryable : IQueryable { diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs index ab4cd0049f..e9e1f2c618 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs @@ -304,6 +304,13 @@ public class EfCoreRepository : RepositoryBase, IE } } + public override async Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + var dbContext = await GetDbContextAsync(); + var dbSet = dbContext.Set(); + await dbSet.Where(predicate).ExecuteDeleteAsync(GetCancellationToken(cancellationToken)); + } + public virtual async Task EnsureCollectionLoadedAsync( TEntity entity, Expression>> propertyExpression, diff --git a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs index 61bb9745e2..de7afbe3c6 100644 --- a/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs +++ b/framework/src/Volo.Abp.MemoryDb/Volo/Abp/Domain/Repositories/MemoryDb/MemoryDbRepository.cs @@ -205,6 +205,11 @@ public class MemoryDbRepository : RepositoryBase> predicate, CancellationToken cancellationToken = default) + { + await DeleteAsync(predicate, true, cancellationToken); + } + public override async Task InsertAsync( TEntity entity, bool autoSave = false, 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 e128c8dee8..5345335092 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 @@ -484,6 +484,11 @@ public class MongoDbRepository await DeleteManyAsync(entities, autoSave, cancellationToken); } + public override async Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + await DeleteAsync(predicate, true, cancellationToken); + } + [Obsolete("Use GetQueryableAsync method.")] protected override IQueryable GetQueryable() { diff --git a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs index 116a3729b4..e6e17b253c 100644 --- a/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs +++ b/framework/test/Volo.Abp.Ddd.Tests/Volo/Abp/Domain/Repositories/RepositoryRegistration_Tests.cs @@ -317,6 +317,11 @@ public class RepositoryRegistration_Tests throw new NotImplementedException(); } + public override Task DeleteDirectAsync(Expression> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + public override Task InsertAsync(TEntity entity, bool autoSave = false, CancellationToken cancellationToken = default) { throw new NotImplementedException(); diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs index 5ddce446a1..4e0279a17e 100644 --- a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/Repositories/Repository_Basic_Tests.cs @@ -1,8 +1,13 @@ using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; using Shouldly; +using Volo.Abp.Data; using Volo.Abp.Domain.Repositories; +using Volo.Abp.TestApp; +using Volo.Abp.TestApp.Domain; using Volo.Abp.TestApp.Testing; +using Volo.Abp.Uow; using Xunit; namespace Volo.Abp.EntityFrameworkCore.Repositories; @@ -28,4 +33,20 @@ public class Repository_Basic_Tests : Repository_Basic_Tests().Begin()) + { + await PersonRepository.DeleteAsync(x => x.Id == TestDataBuilder.UserDouglasId); + (await PersonRepository.GetDbContextAsync()).ChangeTracker.Entries().ShouldContain(x => x.Entity.Id == TestDataBuilder.UserDouglasId); + } + + using (ServiceProvider.GetRequiredService().Begin()) + { + await PersonRepository.DeleteDirectAsync(x => x.Id == TestDataBuilder.UserDouglasId); + (await PersonRepository.GetDbContextAsync()).ChangeTracker.Entries().ShouldNotContain(x => x.Entity.Id == TestDataBuilder.UserDouglasId); + } + } }