Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: change the AbstractEntitySearchService to use reflection to work with mongo v3 linq provider #311

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,7 @@ public async Task<EntityPagedResponse<ChangeTrackingEntity<TEntityKey, TEntity>>
{
query = query.Where(x => x.EntityId.Equals(searchRequest.EntityId));

var filter = GetSearchExpression(searchRequest);

if (filter != null)
{
query = query.Where(filter);
}
query = GetSearchExpressions(searchRequest).Aggregate(query, (current, expression) => current.Where(expression));

if (_searchHandler != null)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Firebend.AutoCrud.ChangeTracking.Interfaces;
Expand Down Expand Up @@ -51,12 +52,7 @@ public async Task<EntityPagedResponse<ChangeTrackingEntity<TEntityKey, TEntity>>

query = query.Where(x => x.EntityId.Equals(searchRequest.EntityId));

var filter = GetSearchExpression(searchRequest);

if (filter != null)
{
query = query.Where(filter);
}
query = GetSearchExpressions(searchRequest).Aggregate(query, (current, expression) => current.Where(expression));

if (searchRequest.OrderBy == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Firebend.AutoCrud.Core.Extensions;
using Firebend.AutoCrud.Core.Implementations;
using Firebend.AutoCrud.Core.Interfaces.Models;
Expand All @@ -11,61 +12,82 @@ namespace Firebend.AutoCrud.Core.Abstractions.Services;
public abstract class AbstractEntitySearchService<TEntity, TSearch> : BaseDisposable
where TSearch : IEntitySearchRequest
{
protected Expression<Func<TEntity, bool>> GetSearchExpression(TSearch search, Expression<Func<TEntity, bool>> customFilter = null)
{
var functions = new List<Expression<Func<TEntity, bool>>>();
private Type _myType;
private MethodInfo _yieldDateFiltersMethodInfo;
private MethodInfo _yieldActiveFiltersMethodInfo;

if (search is IActiveEntitySearchRequest { IsDeleted: not null } activeEntitySearchRequest)
{
Expression<Func<IActiveEntity, bool>> expression = activeEntitySearchRequest.IsDeleted.Value
? x => x.IsDeleted
: x => !x.IsDeleted;
private Type MyType => _myType ??= typeof(AbstractEntitySearchService<TEntity, TSearch>);

functions.Add(Expression.Lambda<Func<TEntity, bool>>(expression.Body, expression.Parameters));
}
private MethodInfo YieldDateFiltersMethodInfo => _yieldDateFiltersMethodInfo ??= MyType
.GetMethod(nameof(YieldDateFilters), BindingFlags.Static | BindingFlags.NonPublic)
?.MakeGenericMethod(typeof(TEntity));

private MethodInfo YieldActiveFiltersMethodInfo => _yieldActiveFiltersMethodInfo ??= MyType
.GetMethod(nameof(YieldActiveFilters), BindingFlags.Static | BindingFlags.NonPublic)
?.MakeGenericMethod(typeof(TEntity));

if (search is IModifiedEntitySearchRequest modifiedEntitySearchRequest)

protected IEnumerable<Expression<Func<TEntity, bool>>> GetSearchExpressions(TSearch search)
{
if (search is IActiveEntitySearchRequest { IsDeleted: not null })
{
if (modifiedEntitySearchRequest.CreatedStartDate.HasValue)
foreach (var func in InvokeFiltering(YieldActiveFiltersMethodInfo, search))
{
Expression<Func<IModifiedEntity, bool>> expression =
x => x.CreatedDate >= modifiedEntitySearchRequest.CreatedStartDate;

functions.Add(Expression.Lambda<Func<TEntity, bool>>(expression.Body, expression.Parameters));
yield return func;
}
}

if (modifiedEntitySearchRequest.CreatedEndDate.HasValue)
if (search is IModifiedEntitySearchRequest)
{
foreach (var func in InvokeFiltering(YieldDateFiltersMethodInfo, search))
{
Expression<Func<IModifiedEntity, bool>> expression =
x => x.CreatedDate <= modifiedEntitySearchRequest.CreatedEndDate;

functions.Add(Expression.Lambda<Func<TEntity, bool>>(expression.Body, expression.Parameters));
yield return func;
}
}
}

if (modifiedEntitySearchRequest.ModifiedStartDate.HasValue)
{
Expression<Func<IModifiedEntity, bool>> expression =
x => x.ModifiedDate >= modifiedEntitySearchRequest.ModifiedStartDate;
private IEnumerable<Expression<Func<TEntity, bool>>> InvokeFiltering(MethodInfo method, TSearch search)
{
var invoked = method.Invoke(this, [search]);
var enumerable = invoked as IEnumerable<Expression<Func<TEntity, bool>>>;
return enumerable;
}

functions.Add(Expression.Lambda<Func<TEntity, bool>>(expression.Body, expression.Parameters));
}
private static IEnumerable<Expression<Func<T, bool>>> YieldDateFilters<T>(
IModifiedEntitySearchRequest modifiedEntitySearchRequest)
where T : TEntity, IModifiedEntity
{
if (modifiedEntitySearchRequest.CreatedStartDate.HasValue)
{
yield return x => x.CreatedDate >= modifiedEntitySearchRequest.CreatedStartDate;
}

if (modifiedEntitySearchRequest.ModifiedEndDate.HasValue)
{
Expression<Func<IModifiedEntity, bool>> expression =
x => x.ModifiedDate <= modifiedEntitySearchRequest.ModifiedEndDate;
if (modifiedEntitySearchRequest.CreatedEndDate.HasValue)
{
yield return x => x.CreatedDate <= modifiedEntitySearchRequest.CreatedEndDate;
}

functions.Add(Expression.Lambda<Func<TEntity, bool>>(expression.Body, expression.Parameters));
}
if (modifiedEntitySearchRequest.ModifiedStartDate.HasValue)
{
yield return x => x.ModifiedDate >= modifiedEntitySearchRequest.ModifiedStartDate;
}

if (customFilter != null)
if (modifiedEntitySearchRequest.ModifiedEndDate.HasValue)
{
functions.Add(customFilter);
yield return x => x.ModifiedDate <= modifiedEntitySearchRequest.ModifiedEndDate;
}
}

return functions.Aggregate(
default(Expression<Func<TEntity, bool>>),
(aggregate, filter) => aggregate.AndAlso(filter));
private static IEnumerable<Expression<Func<T, bool>>> YieldActiveFilters<T>(
IActiveEntitySearchRequest activeEntitySearchRequest)
where T : IActiveEntity, TEntity
{
var isDeleted = activeEntitySearchRequest.IsDeleted.GetValueOrDefault();

yield return isDeleted switch
{
true => x => x.IsDeleted,
false => x => !x.IsDeleted
};
}
}
2 changes: 1 addition & 1 deletion Firebend.AutoCrud.Core/Extensions/OrderByExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static (Expression<Func<T, object>> order, bool ascending)[] ToOrderByGro
{
if (source is null || source.Length <= 0)
{
return Array.Empty<(Expression<Func<T, object>> order, bool ascending)>();
return [];
}

return source
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,7 @@ public async Task<EntityPagedResponse<TEntity>> PageAsync(TSearch request,

await using (context)
{
var expression = GetSearchExpression(request);

if (expression != null)
{
query = query.Where(expression);
}
query = GetSearchExpressions(request).Aggregate(query, (current, expression) => current.Where(expression));

if (_searchHandler != null)
{
Expand Down
4 changes: 4 additions & 0 deletions Firebend.AutoCrud.IntegrationTests/BaseTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ private async Task PageAsync()
.SetQueryParam("pageSize", 10)
.SetQueryParam("isDeleted", "false")
.SetQueryParam("orderBy", "createdDate:desc")
.SetQueryParam("CreatedStartDate", "1968-08-09")
.SetQueryParam("CreatedEndDate", "2068-08-09")
.SetQueryParam("ModifiedStartDate", "1968-08-09")
.SetQueryParam("ModifiedEndDate", "2068-08-09")
.SetQueryParam("doCount", true)
.GetAsync();

Expand Down
7 changes: 1 addition & 6 deletions Firebend.AutoCrud.Mongo/Services/MongoEntitySearchService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,7 @@ public async Task<EntityPagedResponse<TEntity>> PageAsync(TSearch request, IEnti

var query = await _readClient.GetQueryableAsync(firstStageFilter, entityTransaction, cancellationToken);

var expression = GetSearchExpression(request);

if (expression != null)
{
query = query.Where(expression);
}
query = GetSearchExpressions(request).Aggregate(query, (current, expression) => current.Where(expression));

var paged = await _readClient.GetPagedResponseAsync(query, request, cancellationToken);

Expand Down
Loading