From 69233b35137e84cf8329587a0713aecad57b6dbb Mon Sep 17 00:00:00 2001
From: Fati Iseni <fati.iseni@pozitrongroup.com>
Date: Sun, 9 Mar 2025 20:53:46 +0100
Subject: [PATCH 1/2] Removed the obsolete GetBySpec repo methods.

---
 .../RepositoryBaseOfT.cs                      | 14 -----------
 .../ContextFactoryRepositoryBaseOfT.cs        | 14 -----------
 .../RepositoryBaseOfT.cs                      | 14 -----------
 .../IReadRepositoryBase.cs                    | 23 -------------------
 .../RepositoryOfT_GetBySpec.cs                | 16 ++++++-------
 5 files changed, 8 insertions(+), 73 deletions(-)

diff --git a/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs b/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs
index e9585301..122e2d57 100644
--- a/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs
+++ b/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs
@@ -96,20 +96,6 @@ public virtual async Task<T> GetByIdAsync<TId>(TId id, CancellationToken cancell
         return await DbContext.Set<T>().FindAsync(cancellationToken: cancellationToken, new object[] { id });
     }
 
-    /// <inheritdoc/>
-    [Obsolete("Use FirstOrDefaultAsync<T> or SingleOrDefaultAsync<T> instead. The SingleOrDefaultAsync<T> can be applied only to SingleResultSpecification<T> specifications.")]
-    public virtual async Task<T> GetBySpecAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
-    {
-        return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken);
-    }
-
-    /// <inheritdoc/>
-    [Obsolete("Use FirstOrDefaultAsync<T> or SingleOrDefaultAsync<T> instead. The SingleOrDefaultAsync<T> can be applied only to SingleResultSpecification<T> specifications.")]
-    public virtual async Task<TResult> GetBySpecAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default)
-    {
-        return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken);
-    }
-
     /// <inheritdoc/>
     public virtual async Task<T> FirstOrDefaultAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
     {
diff --git a/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs b/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs
index 0b64c75a..a87191f9 100644
--- a/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs
+++ b/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs
@@ -26,20 +26,6 @@ public ContextFactoryRepositoryBaseOfT(IDbContextFactory<TContext> dbContextFact
         return await dbContext.Set<TEntity>().FindAsync(new object[] { id }, cancellationToken: cancellationToken);
     }
 
-    /// <inheritdoc/>
-    public async Task<TEntity?> GetBySpecAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default)
-    {
-        await using var dbContext = _dbContextFactory.CreateDbContext();
-        return await ApplySpecification(specification, dbContext).FirstOrDefaultAsync(cancellationToken);
-    }
-
-    /// <inheritdoc/>
-    public async Task<TResult?> GetBySpecAsync<TResult>(ISpecification<TEntity, TResult> specification, CancellationToken cancellationToken = default)
-    {
-        await using var dbContext = _dbContextFactory.CreateDbContext();
-        return await ApplySpecification(specification, dbContext).FirstOrDefaultAsync(cancellationToken);
-    }
-
     /// <inheritdoc/>
     public async Task<TEntity?> FirstOrDefaultAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default)
     {
diff --git a/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs b/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs
index e4c5bfd9..a3ba8f0d 100644
--- a/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs
+++ b/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs
@@ -91,20 +91,6 @@ public virtual async Task<int> SaveChangesAsync(CancellationToken cancellationTo
         return await DbContext.Set<T>().FindAsync(new object[] { id }, cancellationToken: cancellationToken);
     }
 
-    /// <inheritdoc/>
-    [Obsolete("Use FirstOrDefaultAsync<T> or SingleOrDefaultAsync<T> instead. The SingleOrDefaultAsync<T> can be applied only to SingleResultSpecification<T> specifications.")]
-    public virtual async Task<T?> GetBySpecAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
-    {
-        return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken);
-    }
-
-    /// <inheritdoc/>
-    [Obsolete("Use FirstOrDefaultAsync<T> or SingleOrDefaultAsync<T> instead. The SingleOrDefaultAsync<T> can be applied only to SingleResultSpecification<T> specifications.")]
-    public virtual async Task<TResult?> GetBySpecAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default)
-    {
-        return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken);
-    }
-
     /// <inheritdoc/>
     public virtual async Task<T?> FirstOrDefaultAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
     {
diff --git a/src/Ardalis.Specification/IReadRepositoryBase.cs b/src/Ardalis.Specification/IReadRepositoryBase.cs
index aa6a09e6..c83a43b8 100644
--- a/src/Ardalis.Specification/IReadRepositoryBase.cs
+++ b/src/Ardalis.Specification/IReadRepositoryBase.cs
@@ -21,29 +21,6 @@ public interface IReadRepositoryBase<T> where T : class
     /// </returns>
     Task<T?> GetByIdAsync<TId>(TId id, CancellationToken cancellationToken = default) where TId : notnull;
 
-    /// <summary>
-    /// Finds an entity that matches the encapsulated query logic of the <paramref name="specification"/>.
-    /// </summary>
-    /// <param name="specification">The encapsulated query logic.</param>
-    /// <returns>
-    /// A task that represents the asynchronous operation.
-    /// The task result contains the <typeparamref name="T" />, or <see langword="null"/>.
-    /// </returns>
-    [Obsolete("Use FirstOrDefaultAsync<T> or SingleOrDefaultAsync<T> instead. The SingleOrDefaultAsync<T> can be applied only to SingleResultSpecification<T> specifications.")]
-    Task<T?> GetBySpecAsync(ISpecification<T> specification, CancellationToken cancellationToken = default);
-
-    /// <summary>
-    /// Finds an entity that matches the encapsulated query logic of the <paramref name="specification"/>.
-    /// </summary>
-    /// <typeparam name="TResult">The type of the result.</typeparam>
-    /// <param name="specification">The encapsulated query logic.</param>
-    /// <returns>
-    /// A task that represents the asynchronous operation.
-    /// The task result contains the <typeparamref name="TResult" />.
-    /// </returns>
-    [Obsolete("Use FirstOrDefaultAsync<T> or SingleOrDefaultAsync<T> instead. The SingleOrDefaultAsync<T> can be applied only to SingleResultSpecification<T> specifications.")]
-    Task<TResult?> GetBySpecAsync<TResult>(ISpecification<T, TResult> specification, CancellationToken cancellationToken = default);
-
     /// <summary>
     /// Returns the first element of a sequence, or a default value if the sequence contains no elements.
     /// </summary>
diff --git a/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_GetBySpec.cs b/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_GetBySpec.cs
index de56a5b0..8b2f855f 100644
--- a/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_GetBySpec.cs
+++ b/tests/Ardalis.Specification.EntityFramework6.Tests/RepositoryOfT_GetBySpec.cs
@@ -21,7 +21,7 @@ public async Task ReturnsStoreWithProducts_GivenStoreByIdIncludeProductsSpec()
         spec.Query.Where(x => x.Id == StoreSeed.VALID_STORE_ID)
             .Include(x => x.Products);
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result.Name.Should().Be(StoreSeed.VALID_STORE_NAME);
@@ -37,7 +37,7 @@ public async Task ReturnsStoreWithAddress_GivenStoreByIdIncludeAddressSpec()
         spec.Query.Where(x => x.Id == StoreSeed.VALID_STORE_ID)
             .Include(x => x.Address);
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result.Name.Should().Be(StoreSeed.VALID_STORE_NAME);
@@ -54,7 +54,7 @@ public async Task ReturnsStoreWithAddressAndProduct_GivenStoreByIdIncludeAddress
             .Include(x => x.Address)
             .Include(x => x.Products);
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result.Name.Should().Be(StoreSeed.VALID_STORE_NAME);
@@ -71,7 +71,7 @@ public async Task ReturnsStoreWithProducts_GivenStoreByIdIncludeProductsUsingStr
         spec.Query.Where(x => x.Id == StoreSeed.VALID_STORE_ID)
             .Include(nameof(Store.Products));
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result.Name.Should().Be(StoreSeed.VALID_STORE_NAME);
@@ -88,7 +88,7 @@ public async Task ReturnsCompanyWithStoresAndAddress_GivenCompanyByIdIncludeStor
             .Include(x => x.Stores)
             .ThenInclude(x => x.Address);
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result.Name.Should().Be(CompanySeed.VALID_COMPANY_NAME);
@@ -106,7 +106,7 @@ public async Task ReturnsCompanyWithStoresAndProducts_GivenCompanyByIdIncludeSto
             .Include(x => x.Stores)
             .ThenInclude(x => x.Products);
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result.Name.Should().Be(CompanySeed.VALID_COMPANY_NAME);
@@ -123,7 +123,7 @@ public async Task ReturnsUntrackedCompany_GivenCompanyByIdAsUntrackedSpec()
         spec.Query.Where(x => x.Id == CompanySeed.VALID_COMPANY_ID)
             .AsNoTracking();
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result?.Name.Should().Be(CompanySeed.VALID_COMPANY_NAME);
@@ -140,7 +140,7 @@ public async Task ReturnsStoreWithCompanyAndCountryAndStoresForCompany_GivenStor
             .Include(x => x.Company).ThenInclude(x => x!.Country)
             .Include(x => x.Company).ThenInclude(x => x!.Stores).ThenInclude(x => x.Products);
 
-        var result = await repo.GetBySpecAsync(spec);
+        var result = await repo.FirstOrDefaultAsync(spec);
 
         result.Should().NotBeNull();
         result.Name.Should().Be(StoreSeed.VALID_STORE_NAME);

From cc71b976bcd3cc9efa901bc86d5cbaee438bd7fd Mon Sep 17 00:00:00 2001
From: Fati Iseni <fati.iseni@pozitrongroup.com>
Date: Sun, 9 Mar 2025 21:02:09 +0100
Subject: [PATCH 2/2] Return affected rows for Update and Delete repo methods.

---
 .../RepositoryBaseOfT.cs                      | 25 +++++++++++--------
 .../ContextFactoryRepositoryBaseOfT.cs        | 25 +++++++++++--------
 .../RepositoryBaseOfT.cs                      | 25 +++++++++++--------
 src/Ardalis.Specification/IRepositoryBase.cs  | 20 +++++++--------
 4 files changed, 55 insertions(+), 40 deletions(-)

diff --git a/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs b/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs
index 122e2d57..614bdacb 100644
--- a/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs
+++ b/src/Ardalis.Specification.EntityFramework6/RepositoryBaseOfT.cs
@@ -41,47 +41,52 @@ public virtual async Task<IEnumerable<T>> AddRangeAsync(IEnumerable<T> entities,
     }
 
     /// <inheritdoc/>
-    public virtual async Task UpdateAsync(T entity, CancellationToken cancellationToken = default)
+    public virtual async Task<int> UpdateAsync(T entity, CancellationToken cancellationToken = default)
     {
         DbContext.Entry(entity).State = EntityState.Modified;
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task UpdateRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
+    public virtual async Task<int> UpdateRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
     {
         foreach (var entity in entities)
         {
             DbContext.Entry(entity).State = EntityState.Modified;
         }
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task DeleteAsync(T entity, CancellationToken cancellationToken = default)
+    public virtual async Task<int> DeleteAsync(T entity, CancellationToken cancellationToken = default)
     {
         DbContext.Set<T>().Remove(entity);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task DeleteRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
+    public virtual async Task<int> DeleteRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
     {
         DbContext.Set<T>().RemoveRange(entities);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task DeleteRangeAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
+    public virtual async Task<int> DeleteRangeAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
     {
         var query = ApplySpecification(specification);
         DbContext.Set<T>().RemoveRange(query);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
diff --git a/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs b/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs
index a87191f9..bfffea09 100644
--- a/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs
+++ b/src/Ardalis.Specification.EntityFrameworkCore/ContextFactoryRepositoryBaseOfT.cs
@@ -138,49 +138,54 @@ public async Task<IEnumerable<TEntity>> AddRangeAsync(IEnumerable<TEntity> entit
     }
 
     /// <inheritdoc/>
-    public async Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default)
+    public async Task<int> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default)
     {
         await using var dbContext = _dbContextFactory.CreateDbContext();
         dbContext.Set<TEntity>().Update(entity);
 
-        await SaveChangesAsync(dbContext, cancellationToken);
+        var result = await SaveChangesAsync(dbContext, cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public async Task UpdateRangeAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
+    public async Task<int> UpdateRangeAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
     {
         await using var dbContext = _dbContextFactory.CreateDbContext();
         dbContext.Set<TEntity>().UpdateRange(entities);
 
-        await SaveChangesAsync(dbContext, cancellationToken);
+        var result = await SaveChangesAsync(dbContext, cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default)
+    public async Task<int> DeleteAsync(TEntity entity, CancellationToken cancellationToken = default)
     {
         await using var dbContext = _dbContextFactory.CreateDbContext();
         dbContext.Set<TEntity>().Remove(entity);
 
-        await SaveChangesAsync(dbContext, cancellationToken);
+        var result = await SaveChangesAsync(dbContext, cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public async Task DeleteRangeAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
+    public async Task<int> DeleteRangeAsync(IEnumerable<TEntity> entities, CancellationToken cancellationToken = default)
     {
         await using var dbContext = _dbContextFactory.CreateDbContext();
         dbContext.Set<TEntity>().RemoveRange(entities);
 
-        await SaveChangesAsync(dbContext, cancellationToken);
+        var result = await SaveChangesAsync(dbContext, cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public async Task DeleteRangeAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default)
+    public async Task<int> DeleteRangeAsync(ISpecification<TEntity> specification, CancellationToken cancellationToken = default)
     {
         await using var dbContext = _dbContextFactory.CreateDbContext();
         var query = ApplySpecification(specification, dbContext);
         dbContext.Set<TEntity>().RemoveRange(query);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(dbContext, cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
diff --git a/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs b/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs
index a3ba8f0d..a7961709 100644
--- a/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs
+++ b/src/Ardalis.Specification.EntityFrameworkCore/RepositoryBaseOfT.cs
@@ -39,44 +39,49 @@ public virtual async Task<IEnumerable<T>> AddRangeAsync(IEnumerable<T> entities,
     }
 
     /// <inheritdoc/>
-    public virtual async Task UpdateAsync(T entity, CancellationToken cancellationToken = default)
+    public virtual async Task<int> UpdateAsync(T entity, CancellationToken cancellationToken = default)
     {
         DbContext.Set<T>().Update(entity);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task UpdateRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
+    public virtual async Task<int> UpdateRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
     {
         DbContext.Set<T>().UpdateRange(entities);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task DeleteAsync(T entity, CancellationToken cancellationToken = default)
+    public virtual async Task<int> DeleteAsync(T entity, CancellationToken cancellationToken = default)
     {
         DbContext.Set<T>().Remove(entity);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task DeleteRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
+    public virtual async Task<int> DeleteRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default)
     {
         DbContext.Set<T>().RemoveRange(entities);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
-    public virtual async Task DeleteRangeAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
+    public virtual async Task<int> DeleteRangeAsync(ISpecification<T> specification, CancellationToken cancellationToken = default)
     {
         var query = ApplySpecification(specification);
         DbContext.Set<T>().RemoveRange(query);
 
-        await SaveChangesAsync(cancellationToken);
+        var result = await SaveChangesAsync(cancellationToken);
+        return result;
     }
 
     /// <inheritdoc/>
diff --git a/src/Ardalis.Specification/IRepositoryBase.cs b/src/Ardalis.Specification/IRepositoryBase.cs
index 6ad53246..e5148250 100644
--- a/src/Ardalis.Specification/IRepositoryBase.cs
+++ b/src/Ardalis.Specification/IRepositoryBase.cs
@@ -35,38 +35,38 @@ public interface IRepositoryBase<T> : IReadRepositoryBase<T> where T : class
     /// Updates an entity in the database
     /// </summary>
     /// <param name="entity">The entity to update.</param>
-    /// <returns>A task that represents the asynchronous operation.</returns>
-    Task UpdateAsync(T entity, CancellationToken cancellationToken = default);
+    /// <returns>A task that represents the asynchronous operation. The task result contains the number of state entries written to the database.</returns>
+    Task<int> UpdateAsync(T entity, CancellationToken cancellationToken = default);
 
     /// <summary>
     /// Updates the given entities in the database
     /// </summary>
     /// <param name="entities">The entities to update.</param>
     /// <param name="cancellationToken"></param>
-    /// <returns>A task that represents the asynchronous operation.</returns>
-    Task UpdateRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default);
+    /// <returns>A task that represents the asynchronous operation. The task result contains the number of state entries written to the database.</returns>
+    Task<int> UpdateRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default);
 
     /// <summary>
     /// Removes an entity in the database
     /// </summary>
     /// <param name="entity">The entity to delete.</param>
-    /// <returns>A task that represents the asynchronous operation.</returns>
-    Task DeleteAsync(T entity, CancellationToken cancellationToken = default);
+    /// <returns>A task that represents the asynchronous operation. The task result contains the number of state entries written to the database.</returns>
+    Task<int> DeleteAsync(T entity, CancellationToken cancellationToken = default);
 
     /// <summary>
     /// Removes the given entities in the database
     /// </summary>
     /// <param name="entities">The entities to remove.</param>
-    /// <returns>A task that represents the asynchronous operation.</returns>
-    Task DeleteRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default);
+    /// <returns>A task that represents the asynchronous operation. The task result contains the number of state entries written to the database.</returns>
+    Task<int> DeleteRangeAsync(IEnumerable<T> entities, CancellationToken cancellationToken = default);
 
     /// <summary>
     /// Removes the all entities of <typeparamref name="T" />, that matches the encapsulated query logic of the
     /// <paramref name="specification"/>, from the database.
     /// </summary>
     /// <param name="specification">The encapsulated query logic.</param>
-    /// <returns>A task that represents the asynchronous operation.</returns>
-    Task DeleteRangeAsync(ISpecification<T> specification, CancellationToken cancellationToken = default);
+    /// <returns>A task that represents the asynchronous operation. The task result contains the number of state entries written to the database.</returns>
+    Task<int> DeleteRangeAsync(ISpecification<T> specification, CancellationToken cancellationToken = default);
 
     /// <summary>
     /// Persists changes to the database.
