Skip to content

Commit b77c308

Browse files
committed
Fixes
1 parent f3988c4 commit b77c308

File tree

8 files changed

+322
-380
lines changed

8 files changed

+322
-380
lines changed

README.md

Lines changed: 200 additions & 191 deletions
Large diffs are not rendered by default.
Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,73 @@
11
using System.Linq.Expressions;
2-
using KSFramework.KSDomain.AggregatesHelper;
32
using KSFramework.Pagination;
43

54
namespace KSFramework.GenericRepository;
65

76
/// <summary>
8-
/// Represents a generic repository interface for performing CRUD operations on entities.
7+
/// Represents a generic repository contract for performing common data access operations on entities.
98
/// </summary>
109
/// <typeparam name="TEntity">The type of the entity.</typeparam>
1110
public interface IGenericRepository<TEntity> where TEntity : class
1211
{
1312
/// <summary>
14-
/// Retrieves an entity by its identifier asynchronously.
13+
/// Asynchronously retrieves an entity by its unique identifier.
1514
/// </summary>
16-
/// <param name="id">The identifier of the entity.</param>
17-
/// <returns>A task that represents the asynchronous operation. The task result contains the entity if found.</returns>
15+
/// <param name="id">The unique identifier of the entity.</param>
16+
/// <returns>A task representing the asynchronous operation, containing the entity if found; otherwise, null.</returns>
1817
ValueTask<TEntity?> GetByIdAsync(object id);
1918

2019
/// <summary>
21-
/// Retrieves all entities asynchronously.
20+
/// Asynchronously retrieves all entities.
2221
/// </summary>
23-
/// <returns>A task that represents the asynchronous operation. The task result contains the collection of entities.</returns>
22+
/// <returns>A task representing the asynchronous operation, containing a collection of all entities.</returns>
2423
Task<IEnumerable<TEntity>> GetAllAsync();
2524

2625
/// <summary>
27-
/// Retrieves a paginated list of entities asynchronously based on specified criteria.
26+
/// Asynchronously retrieves a paginated list of entities with optional filtering and ordering.
2827
/// </summary>
29-
/// <param name="pageIndex">The index of the page to retrieve (1-based).</param>
30-
/// <param name="pageSize">The size of the page.</param>
31-
/// <param name="where">Optional predicate to filter the entities.</param>
32-
/// <param name="orderBy">Optional property name to order the results by.</param>
33-
/// <param name="desc">Optional flag to indicate descending order.</param>
34-
/// <returns>A task that represents the asynchronous operation. The task result contains the paginated list of entities.</returns>
28+
/// <param name="pageIndex">The index of the page (starting from 1).</param>
29+
/// <param name="pageSize">The number of items per page.</param>
30+
/// <param name="where">Optional filter expression.</param>
31+
/// <param name="orderBy">Optional property name to order by.</param>
32+
/// <param name="desc">Indicates if the order should be descending.</param>
33+
/// <returns>A task representing the asynchronous operation, containing a paginated list of entities.</returns>
3534
Task<PaginatedList<TEntity>> GetPagedAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>>? where = null, string? orderBy = "", bool desc = false);
3635

3736
/// <summary>
38-
/// Retrieves a paginated list of entities synchronously based on specified criteria.
37+
/// Synchronously retrieves a paginated list of entities with optional filtering and ordering.
3938
/// </summary>
40-
/// <param name="pageIndex">The index of the page to retrieve (1-based).</param>
41-
/// <param name="pageSize">The size of the page.</param>
42-
/// <param name="where">Optional predicate to filter the entities.</param>
43-
/// <param name="orderBy">Optional property name to order the results by.</param>
44-
/// <param name="desc">Optional flag to indicate descending order.</param>
39+
/// <param name="pageIndex">The index of the page (starting from 1).</param>
40+
/// <param name="pageSize">The number of items per page.</param>
41+
/// <param name="where">Optional filter expression.</param>
42+
/// <param name="orderBy">Optional property name to order by.</param>
43+
/// <param name="desc">Indicates if the order should be descending.</param>
4544
/// <returns>A paginated list of entities.</returns>
4645
PaginatedList<TEntity> GetPaged(int pageIndex, int pageSize, Expression<Func<TEntity, bool>>? where = null, string? orderBy = "", bool desc = false);
4746

4847
/// <summary>
49-
/// Finds entities that match the specified predicate.
48+
/// Finds entities matching the given predicate.
5049
/// </summary>
51-
/// <param name="predicate">The condition to filter entities.</param>
52-
/// <returns>A collection of entities that match the condition.</returns>
50+
/// <param name="predicate">The condition to match.</param>
51+
/// <returns>A collection of matching entities.</returns>
5352
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
5453

5554
/// <summary>
56-
/// Retrieves a single entity that matches the specified predicate, or null if no match is found.
55+
/// Asynchronously returns a single entity matching the given predicate, or null if none match.
5756
/// </summary>
58-
/// <param name="predicate">The condition to filter the entity.</param>
59-
/// <returns>A task that represents the asynchronous operation. The task result contains the entity if found, otherwise null.</returns>
57+
/// <param name="predicate">The condition to match.</param>
58+
/// <returns>A task representing the asynchronous operation, containing a single entity or null.</returns>
6059
Task<TEntity?> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
6160

6261
/// <summary>
63-
/// Adds a new entity to the repository asynchronously.
62+
/// Asynchronously adds an entity to the repository.
6463
/// </summary>
6564
/// <param name="entity">The entity to add.</param>
66-
/// <returns>A task that represents the asynchronous operation.</returns>
6765
Task AddAsync(TEntity entity);
6866

6967
/// <summary>
70-
/// Adds multiple entities to the repository asynchronously.
68+
/// Asynchronously adds multiple entities to the repository.
7169
/// </summary>
72-
/// <param name="entities">The collection of entities to add.</param>
73-
/// <returns>A task that represents the asynchronous operation.</returns>
70+
/// <param name="entities">The entities to add.</param>
7471
Task AddRangeAsync(IEnumerable<TEntity> entities);
7572

7673
/// <summary>
@@ -82,13 +79,13 @@ public interface IGenericRepository<TEntity> where TEntity : class
8279
/// <summary>
8380
/// Removes multiple entities from the repository.
8481
/// </summary>
85-
/// <param name="entities">The collection of entities to remove.</param>
82+
/// <param name="entities">The entities to remove.</param>
8683
void RemoveRange(IEnumerable<TEntity> entities);
8784

8885
/// <summary>
89-
/// Checks if any entity exists that matches the specified predicate.
86+
/// Asynchronously checks whether any entity matches the given predicate.
9087
/// </summary>
91-
/// <param name="predicate">The condition to check for existence.</param>
92-
/// <returns>A task that represents the asynchronous operation. The task result contains true if a matching entity exists; otherwise, false.</returns>
88+
/// <param name="predicate">The condition to match.</param>
89+
/// <returns>A task representing the asynchronous operation, containing true if any entity matches; otherwise, false.</returns>
9390
Task<bool> IsExistValueForPropertyAsync(Expression<Func<TEntity, bool>> predicate);
94-
}
91+
}
Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
using System.Linq.Expressions;
2-
using KSFramework.KSDomain.AggregatesHelper;
32
using KSFramework.Pagination;
43

54
namespace KSFramework.GenericRepository;
5+
6+
/// <summary>
7+
/// Defines the contract for a generic repository to handle basic CRUD and query operations.
8+
/// </summary>
9+
/// <typeparam name="TEntity">The entity type.</typeparam>
610
public interface IRepository<TEntity> where TEntity : class
711
{
8-
ValueTask<TEntity?> GetByIdAsync(object id);
9-
Task<IEnumerable<TEntity>> GetAllAsync();
10-
Task<PaginatedList<TEntity>> GetPagedAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>>? where = null, string? orderBy = "", bool desc = false);
11-
PaginatedList<TEntity> GetPaged(int pageIndex, int pageSize, Expression<Func<TEntity, bool>>? where = null, string? orderBy = "", bool desc = false);
12-
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate);
13-
Task<TEntity?> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
1412
Task AddAsync(TEntity entity);
1513
Task AddRangeAsync(IEnumerable<TEntity> entities);
16-
14+
IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate, bool asNoTracking = true);
15+
Task<IEnumerable<TEntity>> GetAllAsync(bool asNoTracking = true);
16+
Task<PaginatedList<TEntity>> GetPagedAsync(
17+
int pageIndex,
18+
int pageSize,
19+
Expression<Func<TEntity, bool>>? where = null,
20+
string? orderBy = "",
21+
bool desc = false);
22+
PaginatedList<TEntity> GetPaged(
23+
int pageIndex,
24+
int pageSize,
25+
Expression<Func<TEntity, bool>>? where = null,
26+
string? orderBy = "",
27+
bool desc = false);
28+
ValueTask<TEntity?> GetByIdAsync(object id);
1729
void Remove(TEntity entity);
1830
void RemoveRange(IEnumerable<TEntity> entities);
31+
Task<TEntity?> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
1932
Task<bool> IsExistValueForPropertyAsync(Expression<Func<TEntity, bool>> predicate);
20-
33+
void Update(TEntity entity);
2134
}

src/KSFramework/GenericRepository/Repository.cs

Lines changed: 21 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,56 @@
11
using System.Linq.Expressions;
2-
using KSFramework.KSDomain.AggregatesHelper;
32
using KSFramework.Pagination;
43
using Microsoft.EntityFrameworkCore;
54

65
namespace KSFramework.GenericRepository;
6+
77
/// <summary>
8-
/// Provides a base implementation of the generic repository pattern for entity operations.
8+
/// Provides a base implementation of the <see cref="IGenericRepository{TEntity}"/> interface using Entity Framework Core.
99
/// </summary>
1010
/// <typeparam name="TEntity">The type of the entity.</typeparam>
11-
public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity : class
11+
public abstract class Repository<TEntity> : IGenericRepository<TEntity> where TEntity : class
1212
{
1313
private readonly DbContext Context;
14-
protected DbSet<TEntity> Entity;
14+
/// <summary>
15+
/// Gets the underlying <see cref="DbSet{TEntity}"/> for querying and persisting entities.
16+
/// </summary>
17+
protected readonly DbSet<TEntity> Entity;
1518

1619
/// <summary>
17-
/// Initializes a new instance of the Repository class.
20+
/// Initializes a new instance of the <see cref="Repository{TEntity}"/> class.
1821
/// </summary>
1922
/// <param name="context">The database context.</param>
2023
protected Repository(DbContext context)
2124
{
22-
this.Context = context;
23-
Entity = Context.Set<TEntity>();
25+
Context = context;
26+
Entity = context.Set<TEntity>();
2427
}
2528

26-
/// <summary>
27-
/// Adds a new entity to the repository asynchronously.
28-
/// </summary>
29-
/// <param name="entity">The entity to add.</param>
30-
/// <returns>A task representing the asynchronous operation.</returns>
29+
/// <inheritdoc />
3130
public virtual async Task AddAsync(TEntity entity)
3231
{
3332
await Entity.AddAsync(entity);
3433
}
3534

36-
/// <summary>
37-
/// Adds multiple entities to the repository asynchronously.
38-
/// </summary>
39-
/// <param name="entities">The collection of entities to add.</param>
40-
/// <returns>A task representing the asynchronous operation.</returns>
35+
/// <inheritdoc />
4136
public virtual async Task AddRangeAsync(IEnumerable<TEntity> entities)
4237
{
4338
await Entity.AddRangeAsync(entities);
4439
}
4540

46-
/// <summary>
47-
/// Finds entities that match the specified predicate.
48-
/// </summary>
49-
/// <param name="predicate">The condition to filter entities.</param>
50-
/// <returns>A collection of entities that match the condition.</returns>
41+
/// <inheritdoc />
5142
public virtual IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
5243
{
5344
return Entity.Where(predicate);
5445
}
5546

56-
/// <summary>
57-
/// Retrieves all entities asynchronously.
58-
/// </summary>
59-
/// <returns>A task representing the asynchronous operation, containing all entities.</returns>
47+
/// <inheritdoc />
6048
public virtual async Task<IEnumerable<TEntity>> GetAllAsync()
6149
{
6250
return await Entity.ToListAsync();
6351
}
6452

65-
/// <summary>
66-
/// Retrieves a paginated list of entities asynchronously.
67-
/// </summary>
68-
/// <param name="pageIndex">The index of the page to retrieve.</param>
69-
/// <param name="pageSize">The size of the page.</param>
70-
/// <param name="where">Optional predicate to filter the entities.</param>
71-
/// <param name="orderBy">Optional property name to order the results by.</param>
72-
/// <param name="desc">Optional flag to indicate descending order.</param>
73-
/// <returns>A task representing the asynchronous operation, containing a paginated list of entities.</returns>
53+
/// <inheritdoc />
7454
public virtual async Task<PaginatedList<TEntity>> GetPagedAsync(int pageIndex, int pageSize, Expression<Func<TEntity, bool>>? where = null, string? orderBy = "", bool desc = false)
7555
{
7656
var query = Entity.AsQueryable();
@@ -80,64 +60,38 @@ public virtual async Task<PaginatedList<TEntity>> GetPagedAsync(int pageIndex, i
8060
return await PaginatedList<TEntity>.CreateAsync(query, pageIndex, pageSize, where, orderBy, desc);
8161
}
8262

83-
/// <summary>
84-
/// Retrieves a paginated list of entities synchronously.
85-
/// </summary>
86-
/// <param name="pageIndex">The index of the page to retrieve.</param>
87-
/// <param name="pageSize">The size of the page.</param>
88-
/// <param name="where">Optional predicate to filter the entities.</param>
89-
/// <param name="orderBy">Optional property name to order the results by.</param>
90-
/// <param name="desc">Optional flag to indicate descending order.</param>
91-
/// <returns>A paginated list of entities.</returns>
63+
/// <inheritdoc />
9264
public virtual PaginatedList<TEntity> GetPaged(int pageIndex, int pageSize, Expression<Func<TEntity, bool>>? where = null, string? orderBy = "", bool desc = false)
9365
{
9466
var query = Entity.AsQueryable();
9567
return PaginatedList<TEntity>.Create(query, pageIndex, pageSize, where, orderBy, desc);
9668
}
9769

98-
/// <summary>
99-
/// Retrieves an entity by its identifier asynchronously.
100-
/// </summary>
101-
/// <param name="id">The identifier of the entity.</param>
102-
/// <returns>A task representing the asynchronous operation, containing the entity if found.</returns>
70+
/// <inheritdoc />
10371
public virtual async ValueTask<TEntity?> GetByIdAsync(object id)
10472
{
10573
return await Entity.FindAsync(id);
10674
}
10775

108-
/// <summary>
109-
/// Removes an entity from the repository.
110-
/// </summary>
111-
/// <param name="entity">The entity to remove.</param>
76+
/// <inheritdoc />
11277
public virtual void Remove(TEntity entity)
11378
{
11479
Entity.Remove(entity);
11580
}
11681

117-
/// <summary>
118-
/// Removes multiple entities from the repository.
119-
/// </summary>
120-
/// <param name="entities">The collection of entities to remove.</param>
82+
/// <inheritdoc />
12183
public virtual void RemoveRange(IEnumerable<TEntity> entities)
12284
{
12385
Entity.RemoveRange(entities);
12486
}
12587

126-
/// <summary>
127-
/// Retrieves a single entity that matches the specified predicate, or null if no match is found.
128-
/// </summary>
129-
/// <param name="predicate">The condition to filter the entity.</param>
130-
/// <returns>A task representing the asynchronous operation, containing the entity if found.</returns>
88+
/// <inheritdoc />
13189
public virtual async Task<TEntity?> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
13290
{
13391
return await Entity.SingleOrDefaultAsync(predicate);
13492
}
13593

136-
/// <summary>
137-
/// Checks if any entity exists that matches the specified predicate.
138-
/// </summary>
139-
/// <param name="predicate">The condition to check for existence.</param>
140-
/// <returns>A task representing the asynchronous operation, containing true if a matching entity exists.</returns>
94+
/// <inheritdoc />
14195
public virtual async Task<bool> IsExistValueForPropertyAsync(Expression<Func<TEntity, bool>> predicate)
14296
{
14397
return await Entity.AnyAsync(predicate);

tests/KSFramework/KSFramework.IntegrationTests/GenericRepository/GenericRepositoryTests.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ public GenericRepositoryTests()
2828
protected override void ConfigureServices(IServiceCollection services)
2929
{
3030
base.ConfigureServices(services);
31-
32-
33-
3431
services.AddScoped<IGenericRepository<TestEntity>, TestGenericRepository>();
3532
}
3633

tests/KSFramework/KSFramework.IntegrationTests/IntegrationTestBase.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,7 @@ protected virtual void ConfigureServices(IServiceCollection services)
3939
options.UseInMemoryDatabase("TestDatabase");
4040
});
4141

42-
43-
44-
45-
46-
services.AddScoped<DbContext, TestDbContext>();
42+
services.AddScoped(provider => (DbContext)provider.GetRequiredService<TestDbContext>());
4743

4844
// Register UnitOfWork and IUnitOfWork
4945
services.AddScoped<IUnitOfWork, UnitOfWork>();

tests/KSFramework/KSFramework.IntegrationTests/Messaging/MediatorTests.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using KSFramework.KSMessaging;
22
using KSFramework.KSMessaging.Abstraction;
3+
using KSFramework.KSMessaging.Extensions;
34
using Microsoft.Extensions.DependencyInjection;
45

56
namespace KSFramework.IntegrationTests.Messaging;
@@ -40,9 +41,7 @@ protected override void ConfigureServices(IServiceCollection services)
4041
{
4142
base.ConfigureServices(services);
4243

43-
services.AddScoped<ICommandHandler<TestCommand, string>, TestCommandHandler>();
44-
services.AddScoped<IQueryHandler<TestQuery, string>, TestQueryHandler>();
45-
services.AddScoped<IMediator, Mediator>();
44+
services.AddKSMediator(typeof(MediatorTests).Assembly);
4645
}
4746

4847
[Fact]

0 commit comments

Comments
 (0)