Skip to content

Commit

Permalink
Extended ILinqReportory to include paging/sorting for IQueryable Find…
Browse files Browse the repository at this point in the history
…Query methods. Rolled back MediatR due to validation issue.
  • Loading branch information
jasonmwebb-lv committed Jul 24, 2024
1 parent d562a49 commit f2aa5f3
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 22 deletions.
4 changes: 2 additions & 2 deletions Src/RCommon.Core/Extensions/IQueryableExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ private static MethodInfo GetLikeMethod(string value, char wildcard)
return stringType.GetMethod(methodName, new Type[] { stringType });
}

public static IPaginatedList<T> ToPaginatedList<T>(this IQueryable<T> source, int? pageIndex, int pageSize)
public static IPaginatedList<T> ToPaginatedList<T>(this IQueryable<T> source, int pageNumber = 1, int pageSize = 10)
{
Guard.IsNotNegativeOrZero(pageSize, "pageSize");

return new PaginatedList<T>(source, pageIndex, pageSize);
return new PaginatedList<T>(source, pageNumber, pageSize);
}

}
Expand Down
2 changes: 1 addition & 1 deletion Src/RCommon.Core/IPagedSpecification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace RCommon
{
public interface IPagedSpecification<T> : ISpecification<T>
{
public int PageIndex { get; }
public int PageNumber { get; }
public int PageSize { get; }

public Expression<Func<T, object>> OrderByExpression { get; }
Expand Down
6 changes: 3 additions & 3 deletions Src/RCommon.Core/PagedSpecification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ namespace RCommon
public class PagedSpecification<T> : Specification<T>, IPagedSpecification<T>
{
public PagedSpecification(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByExpression,
bool orderByAscending, int pageIndex, int pageSize) : base(predicate)
bool orderByAscending, int pageNumber, int pageSize) : base(predicate)
{
OrderByExpression = orderByExpression;
OrderByAscending = orderByAscending;
PageIndex = pageIndex;
PageNumber = pageNumber;
PageSize = pageSize;
}

public Expression<Func<T, object>> OrderByExpression { get; }
public int PageIndex { get; }
public int PageNumber { get; }
public int PageSize { get; }

public bool OrderByAscending { get; set; }
Expand Down
26 changes: 23 additions & 3 deletions Src/RCommon.EfCore/Crud/EFCoreRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,11 @@ public async override Task<IPaginatedList<TEntity>> FindAsync(IPagedSpecificatio
{
query = FindCore(specification.Predicate).OrderByDescending(specification.OrderByExpression);
}
return await Task.FromResult(query.ToPaginatedList(specification.PageIndex, specification.PageSize));
return await Task.FromResult(query.ToPaginatedList(specification.PageNumber, specification.PageSize));
}

public async override Task<IPaginatedList<TEntity>> FindAsync(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int? pageIndex, int pageSize = 1,
bool orderByAscending, int pageNumber = 1, int pageSize = 1,
CancellationToken token = default)
{
IQueryable<TEntity> query;
Expand All @@ -218,7 +218,27 @@ public async override Task<IPaginatedList<TEntity>> FindAsync(Expression<Func<TE
{
query = FindCore(expression).OrderByDescending(orderByExpression);
}
return await Task.FromResult(query.ToPaginatedList(pageIndex, pageSize));
return await Task.FromResult(query.ToPaginatedList(pageNumber, pageSize));
}
public override IQueryable<TEntity> FindQuery(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int pageNumber = 1, int pageSize = 0)
{
IQueryable<TEntity> query;
if (orderByAscending)
{
query = FindCore(expression).OrderBy(orderByExpression);
}
else
{
query = FindCore(expression).OrderByDescending(orderByExpression);
}
return query.Skip((pageNumber - 1) * pageSize).Take(pageSize);
}

public override IQueryable<TEntity> FindQuery(IPagedSpecification<TEntity> specification)
{
return this.FindQuery(specification.Predicate, specification.OrderByExpression,
specification.OrderByAscending, specification.PageNumber, specification.PageSize);
}

public override async Task<TEntity> FindSingleOrDefaultAsync(Expression<Func<TEntity, bool>> expression, CancellationToken token = default)
Expand Down
28 changes: 25 additions & 3 deletions Src/RCommon.Linq2Db/Crud/Linq2DbRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using RCommon;
using RCommon.Persistence.Crud;
using RCommon.Persistence.Transactions;
using LinqToDB.Linq;

namespace RCommon.Persistence.Linq2Db.Crud
{
Expand Down Expand Up @@ -184,11 +185,11 @@ public async override Task<IPaginatedList<TEntity>> FindAsync(IPagedSpecificatio
{
query = FindCore(specification.Predicate).OrderByDescending(specification.OrderByExpression);
}
return await Task.FromResult(query.ToPaginatedList(specification.PageIndex, specification.PageSize));
return await Task.FromResult(query.ToPaginatedList(specification.PageNumber, specification.PageSize));
}

public async override Task<IPaginatedList<TEntity>> FindAsync(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int? pageIndex, int pageSize = 1,
bool orderByAscending, int pageNumber = 1, int pageSize = 1,
CancellationToken token = default)
{
IQueryable<TEntity> query;
Expand All @@ -200,7 +201,28 @@ public async override Task<IPaginatedList<TEntity>> FindAsync(Expression<Func<TE
{
query = FindCore(expression).OrderByDescending(orderByExpression);
}
return await Task.FromResult(query.ToPaginatedList(pageIndex, pageSize));
return await Task.FromResult(query.ToPaginatedList(pageNumber, pageSize));
}

public override IQueryable<TEntity> FindQuery(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int pageNumber = 1, int pageSize = 0)
{
IQueryable<TEntity> query;
if (orderByAscending)
{
query = FindCore(expression).OrderBy(orderByExpression);
}
else
{
query = FindCore(expression).OrderByDescending(orderByExpression);
}
return query.Skip((pageNumber - 1) * pageSize).Take(pageSize);
}

public override IQueryable<TEntity> FindQuery(IPagedSpecification<TEntity> specification)
{
return this.FindQuery(specification.Predicate, specification.OrderByExpression,
specification.OrderByAscending, specification.PageNumber, specification.PageSize);
}

public async override Task<TEntity> FindSingleOrDefaultAsync(Expression<Func<TEntity, bool>> expression, CancellationToken token = default)
Expand Down
2 changes: 1 addition & 1 deletion Src/RCommon.Mediator/Subscribers/IAppRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface IAppRequest

}

public interface IAppRequest<TResponse>
public interface IAppRequest<out TResponse>
{

}
Expand Down
2 changes: 1 addition & 1 deletion Src/RCommon.Mediatr/RCommon.MediatR.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="MediatR" Version="12.4.0" />
<PackageReference Include="MediatR" Version="12.3.0" />
</ItemGroup>

<ItemGroup>
Expand Down
5 changes: 4 additions & 1 deletion Src/RCommon.Persistence/Crud/ILinqRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ public interface ILinqRepository<TEntity>: IQueryable<TEntity>, IReadOnlyReposit
{
IQueryable<TEntity> FindQuery(ISpecification<TEntity> specification);
IQueryable<TEntity> FindQuery(Expression<Func<TEntity, bool>> expression);
IQueryable<TEntity> FindQuery(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int pageNumber = 1, int pageSize = 0);
IQueryable<TEntity> FindQuery(IPagedSpecification<TEntity> specification);

Task<IPaginatedList<TEntity>> FindAsync(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int? pageIndex, int pageSize = 0,
bool orderByAscending, int pageNumber = 1, int pageSize = 0,
CancellationToken token = default);
Task<IPaginatedList<TEntity>> FindAsync(IPagedSpecification<TEntity> specification, CancellationToken token = default);

Expand Down
6 changes: 5 additions & 1 deletion Src/RCommon.Persistence/Crud/LinqRepositoryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,14 @@ public IEnumerable<TEntity> Query(ISpecification<TEntity> specification)
public abstract Task<bool> AnyAsync(ISpecification<TEntity> specification, CancellationToken token = default);

public abstract Task<IPaginatedList<TEntity>> FindAsync(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int? pageIndex, int pageSize = 0,
bool orderByAscending, int pageNumber = 1, int pageSize = 0,
CancellationToken token = default);
public abstract Task<IPaginatedList<TEntity>> FindAsync(IPagedSpecification<TEntity> specification, CancellationToken token = default);

public abstract IQueryable<TEntity> FindQuery(Expression<Func<TEntity, bool>> expression, Expression<Func<TEntity, object>> orderByExpression,
bool orderByAscending, int pageNumber = 1, int pageSize = 0);
public abstract IQueryable<TEntity> FindQuery(IPagedSpecification<TEntity> specification);

public abstract IEagerLoadableQueryable<TEntity> Include(Expression<Func<TEntity, object>> path);

public abstract IEagerLoadableQueryable<TEntity> ThenInclude<TPreviousProperty, TProperty>(Expression<Func<object, TProperty>> path);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public async Task Can_Use_Default_Data_Store()
}

[Test]
public async Task Can_Query_Using_Paging_With_Specific_Params()
public async Task Can_Find_Using_Paging_With_Specific_Params()
{
var repo = new TestRepository(this.ServiceProvider);
repo.Prepare_Can_query_using_paging_with_specific_params();
Expand Down Expand Up @@ -196,7 +196,7 @@ public async Task Can_Query_Using_Paging_With_Specific_Params()
}

[Test]
public async Task Can_Query_Using_Paging_With_Specification()
public async Task Can_Find_Using_Paging_With_Specification()
{
var repo = new TestRepository(this.ServiceProvider);
repo.Prepare_Can_query_using_paging_with_specification();
Expand Down Expand Up @@ -231,7 +231,7 @@ public async Task Can_Query_Using_Paging_With_Specification()
}

[Test]
public async Task Can_Query_Using_Predicate_Builder()
public async Task Can_Find_Using_Predicate_Builder()
{
var repo = new TestRepository(this.ServiceProvider);
repo.Prepare_Can_query_using_predicate_builder();
Expand All @@ -249,6 +249,82 @@ public async Task Can_Query_Using_Predicate_Builder()
Assert.That(customers[4].FirstName == "Homer");
}

[Test]
public async Task Can_Query_Using_Paging_With_Specific_Params()
{
var repo = new TestRepository(this.ServiceProvider);
repo.Prepare_Can_query_using_paging_with_specific_params();

var customerRepo = this.ServiceProvider.GetService<IGraphRepository<Customer>>();

var customers = customerRepo
.FindQuery(x => x.FirstName.StartsWith("Li"), x => x.LastName, true, 1, 10);

Assert.That(customers != null);
Assert.That(customers.Count() == 10);
Assert.That(customers.ToList()[4].FirstName == "Lisa");

customers = customerRepo
.FindQuery(x => x.FirstName.StartsWith("li"), x => x.LastName, true, 2, 10);

Assert.That(customers != null);
Assert.That(customers.Count() == 10);
Assert.That(customers.ToList()[4].FirstName == "Lisa");

repo.CleanUpSeedData();
}

[Test]
public async Task Can_Query_Using_Paging_With_Specification()
{
var repo = new TestRepository(this.ServiceProvider);
repo.Prepare_Can_query_using_paging_with_specification();

var customerRepo = this.ServiceProvider.GetService<IGraphRepository<Customer>>();

var customerSearchSpec = new CustomerSearchSpec("ba", x => x.FirstName, true, 1, 10);

var customers = customerRepo
.FindQuery(customerSearchSpec);

Assert.That(customers != null);
Assert.That(customers.Count() == 10);
Assert.That(customers.ToList()[4].FirstName == "Bart");

customerSearchSpec = new CustomerSearchSpec("ba", x => x.FirstName, true, 2, 10);

customers = customerRepo
.FindQuery(customerSearchSpec);

Assert.That(customers != null);
Assert.That(customers.Count() == 10);

Assert.That(customers.ToList()[4].FirstName == "Bart");

repo.CleanUpSeedData();
}

[Test]
public async Task Can_Query_Using_Predicate_Builder()
{
var repo = new TestRepository(this.ServiceProvider);
repo.Prepare_Can_query_using_predicate_builder();

var customerRepo = this.ServiceProvider.GetService<IGraphRepository<Customer>>();

var predicate = PredicateBuilder.True<Customer>(); // This allows us to build compound expressions
predicate.And(x => x.FirstName.StartsWith("Ho"));

var customers = customerRepo
.FindQuery(predicate, x => x.LastName, true, 1, 10);

Assert.That(customers != null);
Assert.That(customers.Count() == 10);
Assert.That(customers.ToList()[4].FirstName == "Homer");

repo.CleanUpSeedData();
}



[Test]
Expand Down
Loading

0 comments on commit f2aa5f3

Please sign in to comment.