From 69233b35137e84cf8329587a0713aecad57b6dbb Mon Sep 17 00:00:00 2001 From: Fati Iseni 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 GetByIdAsync(TId id, CancellationToken cancell return await DbContext.Set().FindAsync(cancellationToken: cancellationToken, new object[] { id }); } - /// - [Obsolete("Use FirstOrDefaultAsync or SingleOrDefaultAsync instead. The SingleOrDefaultAsync can be applied only to SingleResultSpecification specifications.")] - public virtual async Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default) - { - return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken); - } - - /// - [Obsolete("Use FirstOrDefaultAsync or SingleOrDefaultAsync instead. The SingleOrDefaultAsync can be applied only to SingleResultSpecification specifications.")] - public virtual async Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default) - { - return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken); - } - /// public virtual async Task FirstOrDefaultAsync(ISpecification 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 dbContextFact return await dbContext.Set().FindAsync(new object[] { id }, cancellationToken: cancellationToken); } - /// - public async Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default) - { - await using var dbContext = _dbContextFactory.CreateDbContext(); - return await ApplySpecification(specification, dbContext).FirstOrDefaultAsync(cancellationToken); - } - - /// - public async Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default) - { - await using var dbContext = _dbContextFactory.CreateDbContext(); - return await ApplySpecification(specification, dbContext).FirstOrDefaultAsync(cancellationToken); - } - /// public async Task FirstOrDefaultAsync(ISpecification 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 SaveChangesAsync(CancellationToken cancellationTo return await DbContext.Set().FindAsync(new object[] { id }, cancellationToken: cancellationToken); } - /// - [Obsolete("Use FirstOrDefaultAsync or SingleOrDefaultAsync instead. The SingleOrDefaultAsync can be applied only to SingleResultSpecification specifications.")] - public virtual async Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default) - { - return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken); - } - - /// - [Obsolete("Use FirstOrDefaultAsync or SingleOrDefaultAsync instead. The SingleOrDefaultAsync can be applied only to SingleResultSpecification specifications.")] - public virtual async Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default) - { - return await ApplySpecification(specification).FirstOrDefaultAsync(cancellationToken); - } - /// public virtual async Task FirstOrDefaultAsync(ISpecification 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 where T : class /// Task GetByIdAsync(TId id, CancellationToken cancellationToken = default) where TId : notnull; - /// - /// Finds an entity that matches the encapsulated query logic of the . - /// - /// The encapsulated query logic. - /// - /// A task that represents the asynchronous operation. - /// The task result contains the , or . - /// - [Obsolete("Use FirstOrDefaultAsync or SingleOrDefaultAsync instead. The SingleOrDefaultAsync can be applied only to SingleResultSpecification specifications.")] - Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default); - - /// - /// Finds an entity that matches the encapsulated query logic of the . - /// - /// The type of the result. - /// The encapsulated query logic. - /// - /// A task that represents the asynchronous operation. - /// The task result contains the . - /// - [Obsolete("Use FirstOrDefaultAsync or SingleOrDefaultAsync instead. The SingleOrDefaultAsync can be applied only to SingleResultSpecification specifications.")] - Task GetBySpecAsync(ISpecification specification, CancellationToken cancellationToken = default); - /// /// Returns the first element of a sequence, or a default value if the sequence contains no elements. /// 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 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> AddRangeAsync(IEnumerable entities, } /// - public virtual async Task UpdateAsync(T entity, CancellationToken cancellationToken = default) + public virtual async Task UpdateAsync(T entity, CancellationToken cancellationToken = default) { DbContext.Entry(entity).State = EntityState.Modified; - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// - public virtual async Task UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) + public virtual async Task UpdateRangeAsync(IEnumerable 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; } /// - public virtual async Task DeleteAsync(T entity, CancellationToken cancellationToken = default) + public virtual async Task DeleteAsync(T entity, CancellationToken cancellationToken = default) { DbContext.Set().Remove(entity); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// - public virtual async Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) + public virtual async Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) { DbContext.Set().RemoveRange(entities); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// - public virtual async Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default) + public virtual async Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default) { var query = ApplySpecification(specification); DbContext.Set().RemoveRange(query); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// 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> AddRangeAsync(IEnumerable entit } /// - public async Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default) + public async Task UpdateAsync(TEntity entity, CancellationToken cancellationToken = default) { await using var dbContext = _dbContextFactory.CreateDbContext(); dbContext.Set().Update(entity); - await SaveChangesAsync(dbContext, cancellationToken); + var result = await SaveChangesAsync(dbContext, cancellationToken); + return result; } /// - public async Task UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) + public async Task UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) { await using var dbContext = _dbContextFactory.CreateDbContext(); dbContext.Set().UpdateRange(entities); - await SaveChangesAsync(dbContext, cancellationToken); + var result = await SaveChangesAsync(dbContext, cancellationToken); + return result; } /// - public async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default) + public async Task DeleteAsync(TEntity entity, CancellationToken cancellationToken = default) { await using var dbContext = _dbContextFactory.CreateDbContext(); dbContext.Set().Remove(entity); - await SaveChangesAsync(dbContext, cancellationToken); + var result = await SaveChangesAsync(dbContext, cancellationToken); + return result; } /// - public async Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) + public async Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) { await using var dbContext = _dbContextFactory.CreateDbContext(); dbContext.Set().RemoveRange(entities); - await SaveChangesAsync(dbContext, cancellationToken); + var result = await SaveChangesAsync(dbContext, cancellationToken); + return result; } /// - public async Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default) + public async Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default) { await using var dbContext = _dbContextFactory.CreateDbContext(); var query = ApplySpecification(specification, dbContext); dbContext.Set().RemoveRange(query); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(dbContext, cancellationToken); + return result; } /// 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> AddRangeAsync(IEnumerable entities, } /// - public virtual async Task UpdateAsync(T entity, CancellationToken cancellationToken = default) + public virtual async Task UpdateAsync(T entity, CancellationToken cancellationToken = default) { DbContext.Set().Update(entity); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// - public virtual async Task UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) + public virtual async Task UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) { DbContext.Set().UpdateRange(entities); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// - public virtual async Task DeleteAsync(T entity, CancellationToken cancellationToken = default) + public virtual async Task DeleteAsync(T entity, CancellationToken cancellationToken = default) { DbContext.Set().Remove(entity); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// - public virtual async Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) + public virtual async Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default) { DbContext.Set().RemoveRange(entities); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// - public virtual async Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default) + public virtual async Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default) { var query = ApplySpecification(specification); DbContext.Set().RemoveRange(query); - await SaveChangesAsync(cancellationToken); + var result = await SaveChangesAsync(cancellationToken); + return result; } /// 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 : IReadRepositoryBase where T : class /// Updates an entity in the database /// /// The entity to update. - /// A task that represents the asynchronous operation. - Task UpdateAsync(T entity, CancellationToken cancellationToken = default); + /// A task that represents the asynchronous operation. The task result contains the number of state entries written to the database. + Task UpdateAsync(T entity, CancellationToken cancellationToken = default); /// /// Updates the given entities in the database /// /// The entities to update. /// - /// A task that represents the asynchronous operation. - Task UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default); + /// A task that represents the asynchronous operation. The task result contains the number of state entries written to the database. + Task UpdateRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default); /// /// Removes an entity in the database /// /// The entity to delete. - /// A task that represents the asynchronous operation. - Task DeleteAsync(T entity, CancellationToken cancellationToken = default); + /// A task that represents the asynchronous operation. The task result contains the number of state entries written to the database. + Task DeleteAsync(T entity, CancellationToken cancellationToken = default); /// /// Removes the given entities in the database /// /// The entities to remove. - /// A task that represents the asynchronous operation. - Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default); + /// A task that represents the asynchronous operation. The task result contains the number of state entries written to the database. + Task DeleteRangeAsync(IEnumerable entities, CancellationToken cancellationToken = default); /// /// Removes the all entities of , that matches the encapsulated query logic of the /// , from the database. /// /// The encapsulated query logic. - /// A task that represents the asynchronous operation. - Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default); + /// A task that represents the asynchronous operation. The task result contains the number of state entries written to the database. + Task DeleteRangeAsync(ISpecification specification, CancellationToken cancellationToken = default); /// /// Persists changes to the database.